aboutsummaryrefslogtreecommitdiff
path: root/src/lanes.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lanes.cpp143
1 files changed, 76 insertions, 67 deletions
diff --git a/src/lanes.cpp b/src/lanes.cpp
index 7b730cd..afcac1d 100644
--- a/src/lanes.cpp
+++ b/src/lanes.cpp
@@ -221,38 +221,29 @@ LUAG_FUNC(register)
221// 221//
222LUAG_FUNC(lane_new) 222LUAG_FUNC(lane_new)
223{ 223{
224 // first 9 args: func libs priority globals package required gc_cb name error_trace_level 224 static constexpr int kFuncIdx{ 1 };
225 char const* const _libs_str{ lua_tostring(L_, 2) }; 225 static constexpr int kLibsIdx{ 2 };
226 bool const _have_priority{ !lua_isnoneornil(L_, 3) }; 226 static constexpr int kPrioIdx{ 3 };
227 int const _globals_idx{ lua_isnoneornil(L_, 4) ? 0 : 4 }; 227 static constexpr int kGlobIdx{ 4 };
228 int const _package_idx{ lua_isnoneornil(L_, 5) ? 0 : 5 }; 228 static constexpr int kPackIdx{ 5 };
229 int const _required_idx{ lua_isnoneornil(L_, 6) ? 0 : 6 }; 229 static constexpr int kRequIdx{ 6 };
230 int const _gc_cb_idx{ lua_isnoneornil(L_, 7) ? 0 : 7 }; 230 static constexpr int kGcCbIdx{ 7 };
231 int const _name_idx{ lua_isnoneornil(L_, 8) ? 0 : 8 }; 231 static constexpr int kNameIdx{ 8 };
232 int const _error_trace_level_idx{ 9 }; 232 static constexpr int kErTlIdx{ 9 };
233
234 static constexpr int kFixedArgsIdx{ 9 }; 233 static constexpr int kFixedArgsIdx{ 9 };
234
235 int const _nargs{ lua_gettop(L_) - kFixedArgsIdx }; 235 int const _nargs{ lua_gettop(L_) - kFixedArgsIdx };
236 Universe* const _U{ universe_get(L_) };
237 LUA_ASSERT(L_, _nargs >= 0); 236 LUA_ASSERT(L_, _nargs >= 0);
238 237
239 // public Lanes API accepts a generic range -3/+3 238 Universe* const _U{ universe_get(L_) };
240 // that will be remapped into the platform-specific scheduler priority scheme
241 // On some platforms, -3 is equivalent to -2 and +3 to +2
242 int const _priority{ _have_priority ? static_cast<int>(lua_tointeger(L_, 3)) : kThreadPrioDefault };
243 if (_have_priority && (_priority < kThreadPrioMin || _priority > kThreadPrioMax)) {
244 raise_luaL_error(L_, "Priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, _priority);
245 }
246
247 /* --- Create and prepare the sub state --- */
248 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: setup\n" INDENT_END(_U))); 239 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: setup\n" INDENT_END(_U)));
249 240
250 // populate with selected libraries at the same time. 241 char const* const _libs_str{ lua_tostring(L_, kLibsIdx) };
251 lua_State* const _L2{ luaG_newstate(_U, SourceState{ L_ }, _libs_str) }; // L_: [9 args] ... L2: 242 lua_State* const _L2{ luaG_newstate(_U, SourceState{ L_ }, _libs_str) }; // L_: [fixed] ... L2:
252 STACK_CHECK_START_REL(_L2, 0); 243 STACK_CHECK_START_REL(_L2, 0);
253 244
254 // 'lane' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) 245 // 'lane' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread)
255 Lane* const _lane{ new (_U) Lane{ _U, _L2, static_cast<Lane::ErrorTraceLevel>(lua_tointeger(L_, _error_trace_level_idx)) } }; 246 Lane* const _lane{ new (_U) Lane{ _U, _L2, static_cast<Lane::ErrorTraceLevel>(lua_tointeger(L_, kErTlIdx)) } };
256 if (_lane == nullptr) { 247 if (_lane == nullptr) {
257 raise_luaL_error(L_, "could not create lane: out of memory"); 248 raise_luaL_error(L_, "could not create lane: out of memory");
258 } 249 }
@@ -262,19 +253,13 @@ LUAG_FUNC(lane_new)
262 private: 253 private:
263 lua_State* const L; 254 lua_State* const L;
264 Lane* lane{ nullptr }; 255 Lane* lane{ nullptr };
265 int const gc_cb_idx;
266 int const name_idx;
267 DEBUGSPEW_CODE(Universe* const U);
268 DEBUGSPEW_CODE(DebugSpewIndentScope scope); 256 DEBUGSPEW_CODE(DebugSpewIndentScope scope);
269 257
270 public: 258 public:
271 OnExit(lua_State* L_, Lane* lane_, int gc_cb_idx_, int name_idx_ DEBUGSPEW_COMMA_PARAM(Universe* U_)) 259 OnExit(lua_State* L_, Lane* lane_)
272 : L{ L_ } 260 : L{ L_ }
273 , lane{ lane_ } 261 , lane{ lane_ }
274 , gc_cb_idx{ gc_cb_idx_ } 262 DEBUGSPEW_COMMA_PARAM(scope{ lane_->U })
275 , name_idx{ name_idx_ }
276 DEBUGSPEW_COMMA_PARAM(U{ U_ })
277 DEBUGSPEW_COMMA_PARAM(scope{ U_ })
278 { 263 {
279 } 264 }
280 265
@@ -303,7 +288,7 @@ LUAG_FUNC(lane_new)
303 private: 288 private:
304 void prepareUserData() 289 void prepareUserData()
305 { 290 {
306 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: preparing lane userdata\n" INDENT_END(U))); 291 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: preparing lane userdata\n" INDENT_END(lane->U)));
307 STACK_CHECK_START_REL(L, 0); 292 STACK_CHECK_START_REL(L, 0);
308 // a Lane full userdata needs a single uservalue 293 // a Lane full userdata needs a single uservalue
309 Lane** const _ud{ lua_newuserdatauv<Lane*>(L, 1) }; // L: ... lane 294 Lane** const _ud{ lua_newuserdatauv<Lane*>(L, 1) }; // L: ... lane
@@ -320,9 +305,10 @@ LUAG_FUNC(lane_new)
320 lua_newtable(L); // L: ... lane {uv} 305 lua_newtable(L); // L: ... lane {uv}
321 306
322 // Store the gc_cb callback in the uservalue 307 // Store the gc_cb callback in the uservalue
323 if (gc_cb_idx > 0) { 308 int const _gc_cb_idx{ lua_isnoneornil(L, kGcCbIdx) ? 0 : kGcCbIdx };
309 if (_gc_cb_idx > 0) {
324 kLaneGC.pushKey(L); // L: ... lane {uv} k 310 kLaneGC.pushKey(L); // L: ... lane {uv} k
325 lua_pushvalue(L, gc_cb_idx); // L: ... lane {uv} k gc_cb 311 lua_pushvalue(L, _gc_cb_idx); // L: ... lane {uv} k gc_cb
326 lua_rawset(L, -3); // L: ... lane {uv} 312 lua_rawset(L, -3); // L: ... lane {uv}
327 } 313 }
328 314
@@ -330,19 +316,20 @@ LUAG_FUNC(lane_new)
330 316
331 lua_State* _L2{ lane->L }; 317 lua_State* _L2{ lane->L };
332 STACK_CHECK_START_REL(_L2, 0); 318 STACK_CHECK_START_REL(_L2, 0);
333 char const* const debugName{ (name_idx > 0) ? lua_tostring(L, name_idx) : nullptr }; 319 int const _name_idx{ lua_isnoneornil(L, kNameIdx) ? 0 : kNameIdx };
320 char const* const debugName{ (_name_idx > 0) ? lua_tostring(L, _name_idx) : nullptr };
334 if (debugName) 321 if (debugName)
335 { 322 {
336 if (strcmp(debugName, "auto") != 0) { 323 if (strcmp(debugName, "auto") != 0) {
337 lua_pushstring(_L2, debugName); // L: ... lane L2: "<name>" 324 lua_pushstring(_L2, debugName); // L: ... lane L2: "<name>"
338 } else { 325 } else {
339 lua_Debug ar; 326 lua_Debug ar;
340 lua_pushvalue(L, 1); // L: ... lane func 327 lua_pushvalue(L, 1); // L: ... lane func
341 lua_getinfo(L, ">S", &ar); // L: ... lane 328 lua_getinfo(L, ">S", &ar); // L: ... lane
342 lua_pushfstring(_L2, "%s:%d", ar.short_src, ar.linedefined); // L: ... lane L2: "<name>" 329 lua_pushfstring(_L2, "%s:%d", ar.short_src, ar.linedefined); // L: ... lane L2: "<name>"
343 } 330 }
344 lane->changeDebugName(-1); 331 lane->changeDebugName(-1);
345 lua_pop(_L2, 1); // L: ... lane L2: 332 lua_pop(_L2, 1); // L: ... lane L2:
346 } 333 }
347 STACK_CHECK(_L2, 0); 334 STACK_CHECK(_L2, 0);
348 STACK_CHECK(L, 1); 335 STACK_CHECK(L, 1);
@@ -355,9 +342,26 @@ LUAG_FUNC(lane_new)
355 lane->ready.count_down(); 342 lane->ready.count_down();
356 lane = nullptr; 343 lane = nullptr;
357 } 344 }
358 } onExit{ L_, _lane, _gc_cb_idx, _name_idx DEBUGSPEW_COMMA_PARAM(_U) }; 345 } onExit{ L_, _lane};
359 // launch the thread early, it will sync with a std::latch to parallelize OS thread warmup and L2 preparation 346 // launch the thread early, it will sync with a std::latch to parallelize OS thread warmup and L2 preparation
360 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: launching thread\n" INDENT_END(_U))); 347 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: launching thread\n" INDENT_END(_U)));
348 // public Lanes API accepts a generic range -3/+3
349 // that will be remapped into the platform-specific scheduler priority scheme
350 // On some platforms, -3 is equivalent to -2 and +3 to +2
351 int const _priority{
352 std::invoke([L = L_]() {
353 int const _prio_idx{ lua_isnoneornil(L, kPrioIdx) ? 0 : kPrioIdx };
354 if (_prio_idx == 0) {
355 return kThreadPrioDefault;
356 }
357 int const _priority{ static_cast<int>(lua_tointeger(L, _prio_idx)) };
358 if ((_priority < kThreadPrioMin || _priority > kThreadPrioMax)) {
359 raise_luaL_error(L, "Priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, _priority);
360 }
361 return _priority;
362 })
363 };
364
361 _lane->startThread(_priority); 365 _lane->startThread(_priority);
362 366
363 STACK_GROW(_L2, _nargs + 3); 367 STACK_GROW(_L2, _nargs + 3);
@@ -365,6 +369,7 @@ LUAG_FUNC(lane_new)
365 STACK_CHECK_START_REL(L_, 0); 369 STACK_CHECK_START_REL(L_, 0);
366 370
367 // package 371 // package
372 int const _package_idx{ lua_isnoneornil(L_, kPackIdx) ? 0 : kPackIdx };
368 if (_package_idx != 0) { 373 if (_package_idx != 0) {
369 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: update 'package'\n" INDENT_END(_U))); 374 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: update 'package'\n" INDENT_END(_U)));
370 // when copying with mode LookupMode::LaneBody, should raise an error in case of problem, not leave it one the stack 375 // when copying with mode LookupMode::LaneBody, should raise an error in case of problem, not leave it one the stack
@@ -374,6 +379,7 @@ LUAG_FUNC(lane_new)
374 } 379 }
375 380
376 // modules to require in the target lane *before* the function is transfered! 381 // modules to require in the target lane *before* the function is transfered!
382 int const _required_idx{ lua_isnoneornil(L_, kRequIdx) ? 0 : kRequIdx };
377 if (_required_idx != 0) { 383 if (_required_idx != 0) {
378 int _nbRequired{ 1 }; 384 int _nbRequired{ 1 };
379 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: require 'required' list\n" INDENT_END(_U))); 385 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: require 'required' list\n" INDENT_END(_U)));
@@ -383,8 +389,8 @@ LUAG_FUNC(lane_new)
383 raise_luaL_error(L_, "expected required module list as a table, got %s", luaL_typename(L_, _required_idx)); 389 raise_luaL_error(L_, "expected required module list as a table, got %s", luaL_typename(L_, _required_idx));
384 } 390 }
385 391
386 lua_pushnil(L_); // L_: [8 args] args... nil L2: 392 lua_pushnil(L_); // L_: [fixed] args... nil L2:
387 while (lua_next(L_, _required_idx) != 0) { // L_: [8 args] args... n "modname" L2: 393 while (lua_next(L_, _required_idx) != 0) { // L_: [fixed] args... n "modname" L2:
388 if (lua_type(L_, -1) != LUA_TSTRING || lua_type(L_, -2) != LUA_TNUMBER || lua_tonumber(L_, -2) != _nbRequired) { 394 if (lua_type(L_, -1) != LUA_TSTRING || lua_type(L_, -2) != LUA_TNUMBER || lua_tonumber(L_, -2) != _nbRequired) {
389 raise_luaL_error(L_, "required module list should be a list of strings"); 395 raise_luaL_error(L_, "required module list should be a list of strings");
390 } else { 396 } else {
@@ -394,34 +400,35 @@ LUAG_FUNC(lane_new)
394 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: require '%s'\n" INDENT_END(_U), name)); 400 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: require '%s'\n" INDENT_END(_U), name));
395 401
396 // require the module in the target lane 402 // require the module in the target lane
397 lua_getglobal(_L2, "require"); // L_: [8 args] args... n "modname" L2: require()? 403 lua_getglobal(_L2, "require"); // L_: [fixed] args... n "modname" L2: require()?
398 if (lua_isnil(_L2, -1)) { 404 if (lua_isnil(_L2, -1)) {
399 lua_pop(_L2, 1); // L_: [8 args] args... n "modname" L2: 405 lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2:
400 raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first"); 406 raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first");
401 } else { 407 } else {
402 lua_pushlstring(_L2, name, len); // L_: [8 args] args... n "modname" L2: require() name 408 lua_pushlstring(_L2, name, len); // L_: [fixed] args... n "modname" L2: require() name
403 if (lua_pcall(_L2, 1, 1, 0) != LUA_OK) { // L_: [8 args] args... n "modname" L2: ret/errcode 409 if (lua_pcall(_L2, 1, 1, 0) != LUA_OK) { // L_: [fixed] args... n "modname" L2: ret/errcode
404 // propagate error to main state if any 410 // propagate error to main state if any
405 InterCopyContext _c{ _U, DestState{ L_ }, SourceState{ _L2 }, {}, {}, {}, {}, {} }; 411 InterCopyContext _c{ _U, DestState{ L_ }, SourceState{ _L2 }, {}, {}, {}, {}, {} };
406 std::ignore = _c.inter_move(1); // L_: [8 args] args... n "modname" error L2: 412 std::ignore = _c.inter_move(1); // L_: [fixed] args... n "modname" error L2:
407 raise_lua_error(L_); 413 raise_lua_error(L_);
408 } 414 }
409 // here the module was successfully required // L_: [8 args] args... n "modname" L2: ret 415 // here the module was successfully required // L_: [fixed] args... n "modname" L2: ret
410 // after requiring the module, register the functions it exported in our name<->function database 416 // after requiring the module, register the functions it exported in our name<->function database
411 populate_func_lookup_table(_L2, -1, name); 417 populate_func_lookup_table(_L2, -1, name);
412 lua_pop(_L2, 1); // L_: [8 args] args... n "modname" L2: 418 lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2:
413 } 419 }
414 } 420 }
415 lua_pop(L_, 1); // L_: func libs priority globals package required gc_cb [... args ...] n 421 lua_pop(L_, 1); // L_: [fixed] args... n L2:
416 ++_nbRequired; 422 ++_nbRequired;
417 } // L_: [8 args] args... 423 } // L_: [fixed] args...
418 } 424 }
419 STACK_CHECK(L_, 0); 425 STACK_CHECK(L_, 0);
420 STACK_CHECK(_L2, 0); // L_: [8 args] args... L2: 426 STACK_CHECK(_L2, 0); // L_: [fixed] args... L2:
421 427
422 // Appending the specified globals to the global environment 428 // Appending the specified globals to the global environment
423 // *after* stdlibs have been loaded and modules required, in case we transfer references to native functions they exposed... 429 // *after* stdlibs have been loaded and modules required, in case we transfer references to native functions they exposed...
424 // 430 //
431 int const _globals_idx{ lua_isnoneornil(L_, kGlobIdx) ? 0 : kGlobIdx };
425 if (_globals_idx != 0) { 432 if (_globals_idx != 0) {
426 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer globals\n" INDENT_END(_U))); 433 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer globals\n" INDENT_END(_U)));
427 if (!lua_istable(L_, _globals_idx)) { 434 if (!lua_istable(L_, _globals_idx)) {
@@ -429,37 +436,37 @@ LUAG_FUNC(lane_new)
429 } 436 }
430 437
431 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); 438 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U });
432 lua_pushnil(L_); // L_: [8 args] args... nil L2: 439 lua_pushnil(L_); // L_: [fixed] args... nil L2:
433 // Lua 5.2 wants us to push the globals table on the stack 440 // Lua 5.2 wants us to push the globals table on the stack
434 InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} }; 441 InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} };
435 lua_pushglobaltable(_L2); // L_: [8 args] args... nil L2: _G 442 lua_pushglobaltable(_L2); // L_: [fixed] args... nil L2: _G
436 while (lua_next(L_, _globals_idx)) { // L_: [8 args] args... k v L2: _G 443 while (lua_next(L_, _globals_idx)) { // L_: [fixed] args... k v L2: _G
437 std::ignore = _c.inter_copy(2); // L_: [8 args] args... k v L2: _G k v 444 std::ignore = _c.inter_copy(2); // L_: [fixed] args... k v L2: _G k v
438 // assign it in L2's globals table 445 // assign it in L2's globals table
439 lua_rawset(_L2, -3); // L_: [8 args] args... k v L2: _G 446 lua_rawset(_L2, -3); // L_: [fixed] args... k v L2: _G
440 lua_pop(L_, 1); // L_: [8 args] args... k 447 lua_pop(L_, 1); // L_: [fixed] args... k
441 } // L_: [8 args] args... 448 } // L_: [fixed] args...
442 lua_pop(_L2, 1); // L_: [8 args] args... L2: 449 lua_pop(_L2, 1); // L_: [fixed] args... L2:
443 } 450 }
444 STACK_CHECK(L_, 0); 451 STACK_CHECK(L_, 0);
445 STACK_CHECK(_L2, 0); 452 STACK_CHECK(_L2, 0);
446 453
447 // Lane main function 454 // Lane main function
448 int const errorHandlerCount{ _lane->pushErrorHandler() }; // L2: eh? 455 [[maybe_unused]] int const errorHandlerCount{ _lane->pushErrorHandler() }; // L_: [fixed] args... L2: eh?
449 LuaType const _func_type{ lua_type_as_enum(L_, 1) }; 456 LuaType const _func_type{ lua_type_as_enum(L_, kFuncIdx) };
450 if (_func_type == LuaType::FUNCTION) { 457 if (_func_type == LuaType::FUNCTION) {
451 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END(_U))); 458 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END(_U)));
452 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); 459 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U });
453 lua_pushvalue(L_, 1); // L_: [8 args] args... func L2: eh? 460 lua_pushvalue(L_, kFuncIdx); // L_: [fixed] args... func L2: eh?
454 InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} }; 461 InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} };
455 InterCopyResult const _res{ _c.inter_move(1) }; // L_: [8 args] args... L2: eh? func 462 InterCopyResult const _res{ _c.inter_move(1) }; // L_: [fixed] args... L2: eh? func
456 if (_res != InterCopyResult::Success) { 463 if (_res != InterCopyResult::Success) {
457 raise_luaL_error(L_, "tried to copy unsupported types"); 464 raise_luaL_error(L_, "tried to copy unsupported types");
458 } 465 }
459 } else if (_func_type == LuaType::STRING) { 466 } else if (_func_type == LuaType::STRING) {
460 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: compile lane body\n" INDENT_END(_U))); 467 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: compile lane body\n" INDENT_END(_U)));
461 // compile the string 468 // compile the string
462 if (luaL_loadstring(_L2, lua_tostring(L_, 1)) != 0) { // L_: [8 args] args... L2: eh? func 469 if (luaL_loadstring(_L2, lua_tostring(L_, kFuncIdx)) != 0) { // L_: [fixed] args... L2: eh? func
463 raise_luaL_error(L_, "error when parsing lane function code"); 470 raise_luaL_error(L_, "error when parsing lane function code");
464 } 471 }
465 } else { 472 } else {
@@ -474,7 +481,7 @@ LUAG_FUNC(lane_new)
474 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END(_U))); 481 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END(_U)));
475 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); 482 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U });
476 InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} }; 483 InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} };
477 InterCopyResult const res{ _c.inter_move(_nargs) }; // L_: [8 args] L2: eh? func args... 484 InterCopyResult const res{ _c.inter_move(_nargs) }; // L_: [fixed] L2: eh? func args...
478 if (res != InterCopyResult::Success) { 485 if (res != InterCopyResult::Success) {
479 raise_luaL_error(L_, "tried to copy unsupported types"); 486 raise_luaL_error(L_, "tried to copy unsupported types");
480 } 487 }
@@ -483,12 +490,14 @@ LUAG_FUNC(lane_new)
483 LUA_ASSERT(L_, lua_gettop(L_) == kFixedArgsIdx); 490 LUA_ASSERT(L_, lua_gettop(L_) == kFixedArgsIdx);
484 491
485 // Store 'lane' in the lane's registry, for 'cancel_test()' (we do cancel tests at pending send/receive). 492 // Store 'lane' in the lane's registry, for 'cancel_test()' (we do cancel tests at pending send/receive).
486 kLanePointerRegKey.setValue(_L2, [lane = _lane](lua_State* L_) { lua_pushlightuserdata(L_, lane); });// L_: [8 args] L2: eh? func args... 493 kLanePointerRegKey.setValue(
494 _L2, [lane = _lane](lua_State* L_) { lua_pushlightuserdata(L_, lane); } // L_: [fixed] L2: eh? func args...
495 );
487 STACK_CHECK(_L2, errorHandlerCount + 1 + _nargs); 496 STACK_CHECK(_L2, errorHandlerCount + 1 + _nargs);
488 497
489 STACK_CHECK_RESET_REL(L_, 0); 498 STACK_CHECK_RESET_REL(L_, 0);
490 // all went well, the lane's thread can start working 499 // all went well, the lane's thread can start working
491 onExit.success(); // L_: [8 args] lane L2: <living its own life> 500 onExit.success(); // L_: [fixed] lane L2: <living its own life>
492 // we should have the lane userdata on top of the stack 501 // we should have the lane userdata on top of the stack
493 STACK_CHECK(L_, 1); 502 STACK_CHECK(L_, 1);
494 return 1; 503 return 1;