aboutsummaryrefslogtreecommitdiff
path: root/src/state.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/state.cpp')
-rw-r--r--src/state.cpp133
1 files changed, 65 insertions, 68 deletions
diff --git a/src/state.cpp b/src/state.cpp
index 7252885..563fbc2 100644
--- a/src/state.cpp
+++ b/src/state.cpp
@@ -53,9 +53,8 @@ THE SOFTWARE.
53// 53//
54[[nodiscard]] static int luaG_new_require(lua_State* L_) 54[[nodiscard]] static int luaG_new_require(lua_State* L_)
55{ 55{
56 int rc; 56 int const _args{ lua_gettop(L_) }; // L_: args
57 int const args = lua_gettop(L_); // L_: args 57 Universe* const _U{ universe_get(L_) };
58 Universe* U = universe_get(L_);
59 // char const* modname = luaL_checkstring(L_, 1); 58 // char const* modname = luaL_checkstring(L_, 1);
60 59
61 STACK_GROW(L_, 1); 60 STACK_GROW(L_, 1);
@@ -66,18 +65,18 @@ THE SOFTWARE.
66 // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would 65 // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would
67 // leave us locked, blocking any future 'require' calls from other lanes. 66 // leave us locked, blocking any future 'require' calls from other lanes.
68 67
69 U->requireMutex.lock(); 68 _U->requireMutex.lock();
70 // starting with Lua 5.4, require may return a second optional value, so we need LUA_MULTRET 69 // starting with Lua 5.4, require may return a second optional value, so we need LUA_MULTRET
71 rc = lua_pcall(L_, args, LUA_MULTRET, 0 /*errfunc*/); // L_: err|result(s) 70 int _rc{ lua_pcall(L_, _args, LUA_MULTRET, 0 /*errfunc*/) }; // L_: err|result(s)
72 U->requireMutex.unlock(); 71 _U->requireMutex.unlock();
73 72
74 // the required module (or an error message) is left on the stack as returned value by original require function 73 // the required module (or an error message) is left on the stack as returned value by original require function
75 74
76 if (rc != LUA_OK) { // LUA_ERRRUN / LUA_ERRMEM ? 75 if (_rc != LUA_OK) { // LUA_ERRRUN / LUA_ERRMEM ?
77 raise_lua_error(L_); 76 raise_lua_error(L_);
78 } 77 }
79 // should be 1 for Lua <= 5.3, 1 or 2 starting with Lua 5.4 78 // should be 1 for Lua <= 5.3, 1 or 2 starting with Lua 5.4
80 return lua_gettop(L_); // L_: result(s) 79 return lua_gettop(L_); // L_: result(s)
81} 80}
82 81
83// ################################################################################################# 82// #################################################################################################
@@ -149,9 +148,7 @@ namespace global
149 { LUA_JITLIBNAME, luaopen_jit }, 148 { LUA_JITLIBNAME, luaopen_jit },
150#endif // LUAJIT_FLAVOR() 149#endif // LUAJIT_FLAVOR()
151 150
152 { kLanesCoreLibName, require_lanes_core }, // So that we can open it like any base library (possible since we have access to the init function) 151 { kLanesCoreLibName, require_lanes_core } // So that we can open it like any base library (possible since we have access to the init function)
153 //
154 { nullptr, nullptr }
155 }; 152 };
156 153
157} // namespace global 154} // namespace global
@@ -160,18 +157,18 @@ namespace global
160 157
161static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_, char const* name_, size_t len_) 158static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_, char const* name_, size_t len_)
162{ 159{
163 for (int i{ 0 }; global::sLibs[i].name; ++i) { 160 for (luaL_Reg const& _entry : global::sLibs) {
164 if (strncmp(name_, global::sLibs[i].name, len_) == 0) { 161 if (strncmp(name_, _entry.name, len_) == 0) {
165 lua_CFunction const libfunc{ global::sLibs[i].func }; 162 lua_CFunction const _libfunc{ _entry.func };
166 if (!libfunc) { 163 if (!_libfunc) {
167 continue; 164 continue;
168 } 165 }
169 name_ = global::sLibs[i].name; // note that the provided name_ doesn't necessarily ends with '\0', hence len_ 166 name_ = _entry.name; // note that the provided name_ doesn't necessarily ends with '\0', hence len_
170 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END(U_), (int) len_, name_)); 167 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END(U_), (int) len_, name_));
171 STACK_CHECK_START_REL(L_, 0); 168 STACK_CHECK_START_REL(L_, 0);
172 // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) 169 // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack)
173 bool const isLanesCore{ libfunc == require_lanes_core }; // don't want to create a global for "lanes.core" 170 bool const isLanesCore{ _libfunc == require_lanes_core }; // don't want to create a global for "lanes.core"
174 luaL_requiref(L_, name_, libfunc, !isLanesCore); // L_: {lib} 171 luaL_requiref(L_, name_, _libfunc, !isLanesCore); // L_: {lib}
175 // lanes.core doesn't declare a global, so scan it here and now 172 // lanes.core doesn't declare a global, so scan it here and now
176 if (isLanesCore) { 173 if (isLanesCore) {
177 populate_func_lookup_table(L_, -1, name_); 174 populate_func_lookup_table(L_, -1, name_);
@@ -196,7 +193,7 @@ static inline void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_, c
196// just like lua_xmove, args are (from, to) 193// just like lua_xmove, args are (from, to)
197static void copy_one_time_settings(Universe* U_, SourceState L1_, DestState L2_) 194static void copy_one_time_settings(Universe* U_, SourceState L1_, DestState L2_)
198{ 195{
199 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U_ }); 196 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ });
200 197
201 STACK_GROW(L1_, 2); 198 STACK_GROW(L1_, 2);
202 STACK_CHECK_START_REL(L1_, 0); 199 STACK_CHECK_START_REL(L1_, 0);
@@ -206,8 +203,8 @@ static void copy_one_time_settings(Universe* U_, SourceState L1_, DestState L2_)
206 203
207 kConfigRegKey.pushValue(L1_); // L1_: config 204 kConfigRegKey.pushValue(L1_); // L1_: config
208 // copy settings from from source to destination registry 205 // copy settings from from source to destination registry
209 InterCopyContext c{ U_, L2_, L1_, {}, {}, {}, {}, {} }; 206 InterCopyContext _c{ U_, L2_, L1_, {}, {}, {}, {}, {} };
210 if (c.inter_move(1) != InterCopyResult::Success) { // L1_: L2_: config 207 if (_c.inter_move(1) != InterCopyResult::Success) { // L1_: L2_: config
211 raise_luaL_error(L1_, "failed to copy settings when loading " kLanesCoreLibName); 208 raise_luaL_error(L1_, "failed to copy settings when loading " kLanesCoreLibName);
212 } 209 }
213 // set L2:_R[kConfigRegKey] = settings 210 // set L2:_R[kConfigRegKey] = settings
@@ -227,8 +224,8 @@ void initializeOnStateCreate(Universe* U_, lua_State* L_)
227 U_->onStateCreateFunc = lua_tocfunction(L_, -1); // L_: settings on_state_create 224 U_->onStateCreateFunc = lua_tocfunction(L_, -1); // L_: settings on_state_create
228 if (U_->onStateCreateFunc != nullptr) { 225 if (U_->onStateCreateFunc != nullptr) {
229 // make sure the function doesn't have upvalues 226 // make sure the function doesn't have upvalues
230 char const* upname = lua_getupvalue(L_, -1, 1); // L_: settings on_state_create upval? 227 char const* _upname{ lua_getupvalue(L_, -1, 1) }; // L_: settings on_state_create upval?
231 if (upname != nullptr) { // should be "" for C functions with upvalues if any 228 if (_upname != nullptr) { // should be "" for C functions with upvalues if any
232 raise_luaL_error(L_, "on_state_create shouldn't have upvalues"); 229 raise_luaL_error(L_, "on_state_create shouldn't have upvalues");
233 } 230 }
234 // remove this C function from the config table so that it doesn't cause problems 231 // remove this C function from the config table so that it doesn't cause problems
@@ -248,29 +245,29 @@ void initializeOnStateCreate(Universe* U_, lua_State* L_)
248 245
249lua_State* create_state([[maybe_unused]] Universe* U_, lua_State* from_) 246lua_State* create_state([[maybe_unused]] Universe* U_, lua_State* from_)
250{ 247{
251 lua_State* L; 248 lua_State* _L;
252#if LUAJIT_FLAVOR() == 64 249#if LUAJIT_FLAVOR() == 64
253 // for some reason, LuaJIT 64 bits does not support creating a state with lua_newstate... 250 // for some reason, LuaJIT 64 bits does not support creating a state with lua_newstate...
254 L = luaL_newstate(); 251 _L = luaL_newstate();
255#else // LUAJIT_FLAVOR() == 64 252#else // LUAJIT_FLAVOR() == 64
256 if (U_->provideAllocator != nullptr) { // we have a function we can call to obtain an allocator 253 if (U_->provideAllocator != nullptr) { // we have a function we can call to obtain an allocator
257 lua_pushcclosure(from_, U_->provideAllocator, 0); 254 lua_pushcclosure(from_, U_->provideAllocator, 0);
258 lua_call(from_, 0, 1); 255 lua_call(from_, 0, 1);
259 { 256 {
260 AllocatorDefinition* const def{ lua_tofulluserdata<AllocatorDefinition>(from_, -1) }; 257 AllocatorDefinition* const def{ lua_tofulluserdata<AllocatorDefinition>(from_, -1) };
261 L = lua_newstate(def->allocF, def->allocUD); 258 _L = lua_newstate(def->allocF, def->allocUD);
262 } 259 }
263 lua_pop(from_, 1); 260 lua_pop(from_, 1);
264 } else { 261 } else {
265 // reuse the allocator provided when the master state was created 262 // reuse the allocator provided when the master state was created
266 L = lua_newstate(U_->protectedAllocator.allocF, U_->protectedAllocator.allocUD); 263 _L = lua_newstate(U_->protectedAllocator.allocF, U_->protectedAllocator.allocUD);
267 } 264 }
268#endif // LUAJIT_FLAVOR() == 64 265#endif // LUAJIT_FLAVOR() == 64
269 266
270 if (L == nullptr) { 267 if (_L == nullptr) {
271 raise_luaL_error(from_, "luaG_newstate() failed while creating state; out of memory"); 268 raise_luaL_error(from_, "luaG_newstate() failed while creating state; out of memory");
272 } 269 }
273 return L; 270 return _L;
274} 271}
275 272
276// ################################################################################################# 273// #################################################################################################
@@ -321,34 +318,34 @@ void callOnStateCreate(Universe* U_, lua_State* L_, lua_State* from_, LookupMode
321 */ 318 */
322lua_State* luaG_newstate(Universe* U_, SourceState from_, char const* libs_) 319lua_State* luaG_newstate(Universe* U_, SourceState from_, char const* libs_)
323{ 320{
324 DestState const L{ create_state(U_, from_) }; 321 DestState const _L{ create_state(U_, from_) };
325 322
326 STACK_GROW(L, 2); 323 STACK_GROW(_L, 2);
327 STACK_CHECK_START_ABS(L, 0); 324 STACK_CHECK_START_ABS(_L, 0);
328 325
329 // copy the universe as a light userdata (only the master state holds the full userdata) 326 // copy the universe as a light userdata (only the master state holds the full userdata)
330 // that way, if Lanes is required in this new state, we'll know we are part of this universe 327 // that way, if Lanes is required in this new state, we'll know we are part of this universe
331 universe_store(L, U_); 328 universe_store(_L, U_);
332 STACK_CHECK(L, 0); 329 STACK_CHECK(_L, 0);
333 330
334 // we'll need this every time we transfer some C function from/to this state 331 // we'll need this every time we transfer some C function from/to this state
335 kLookupRegKey.setValue(L, [](lua_State* L_) { lua_newtable(L_); }); 332 kLookupRegKey.setValue(_L, [](lua_State* L_) { lua_newtable(L_); });
336 STACK_CHECK(L, 0); 333 STACK_CHECK(_L, 0);
337 334
338 // neither libs (not even 'base') nor special init func: we are done 335 // neither libs (not even 'base') nor special init func: we are done
339 if (libs_ == nullptr && U_->onStateCreateFunc == nullptr) { 336 if (libs_ == nullptr && U_->onStateCreateFunc == nullptr) {
340 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "luaG_newstate(nullptr)\n" INDENT_END(U_))); 337 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "luaG_newstate(nullptr)\n" INDENT_END(U_)));
341 return L; 338 return _L;
342 } 339 }
343 340
344 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END(U_))); 341 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END(U_)));
345 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U_ }); 342 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U_ });
346 343
347 // copy settings (for example because it may contain a Lua on_state_create function) 344 // copy settings (for example because it may contain a Lua on_state_create function)
348 copy_one_time_settings(U_, from_, L); 345 copy_one_time_settings(U_, from_, _L);
349 346
350 // 'lua.c' stops GC during initialization so perhaps it is a good idea. :) 347 // 'lua.c' stops GC during initialization so perhaps it is a good idea. :)
351 lua_gc(L, LUA_GCSTOP, 0); 348 lua_gc(_L, LUA_GCSTOP, 0);
352 349
353 // Anything causes 'base' to be taken in 350 // Anything causes 'base' to be taken in
354 if (libs_ != nullptr) { 351 if (libs_ != nullptr) {
@@ -356,24 +353,24 @@ lua_State* luaG_newstate(Universe* U_, SourceState from_, char const* libs_)
356 // as we are called from luaopen_lanes_core() already, and that would deadlock 353 // as we are called from luaopen_lanes_core() already, and that would deadlock
357 if (libs_[0] == '*' && libs_[1] == 0) { 354 if (libs_[0] == '*' && libs_[1] == 0) {
358 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END(U_))); 355 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END(U_)));
359 luaL_openlibs(L); 356 luaL_openlibs(_L);
360 // don't forget lanes.core for regular lane states 357 // don't forget lanes.core for regular lane states
361 open1lib(DEBUGSPEW_PARAM_COMMA(U_) L, kLanesCoreLibName); 358 open1lib(DEBUGSPEW_PARAM_COMMA(U_) _L, kLanesCoreLibName);
362 libs_ = nullptr; // done with libs 359 libs_ = nullptr; // done with libs
363 } else { 360 } else {
364 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "opening base library\n" INDENT_END(U_))); 361 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "opening base library\n" INDENT_END(U_)));
365#if LUA_VERSION_NUM >= 502 362#if LUA_VERSION_NUM >= 502
366 // open base library the same way as in luaL_openlibs() 363 // open base library the same way as in luaL_openlibs()
367 luaL_requiref(L, "_G", luaopen_base, 1); 364 luaL_requiref(_L, "_G", luaopen_base, 1);
368 lua_pop(L, 1); 365 lua_pop(_L, 1);
369#else // LUA_VERSION_NUM 366#else // LUA_VERSION_NUM
370 lua_pushcfunction(L, luaopen_base); 367 lua_pushcfunction(_L, luaopen_base);
371 lua_pushstring(L, ""); 368 lua_pushstring(_L, "");
372 lua_call(L, 1, 0); 369 lua_call(_L, 1, 0);
373#endif // LUA_VERSION_NUM 370#endif // LUA_VERSION_NUM
374 } 371 }
375 } 372 }
376 STACK_CHECK(L, 0); 373 STACK_CHECK(_L, 0);
377 374
378 // scan all libraries, open them one by one 375 // scan all libraries, open them one by one
379 if (libs_) { 376 if (libs_) {
@@ -387,40 +384,40 @@ lua_State* luaG_newstate(Universe* U_, SourceState from_, char const* libs_)
387 while (isalnum(p[len]) || p[len] == '.') 384 while (isalnum(p[len]) || p[len] == '.')
388 ++len; 385 ++len;
389 // open library 386 // open library
390 open1lib(DEBUGSPEW_PARAM_COMMA(U_) L, p, len); 387 open1lib(DEBUGSPEW_PARAM_COMMA(U_) _L, p, len);
391 } 388 }
392 } 389 }
393 lua_gc(L, LUA_GCRESTART, 0); 390 lua_gc(_L, LUA_GCRESTART, 0);
394 391
395 serialize_require(DEBUGSPEW_PARAM_COMMA(U_) L); 392 serialize_require(DEBUGSPEW_PARAM_COMMA(U_) _L);
396 393
397 // call this after the base libraries are loaded and GC is restarted 394 // call this after the base libraries are loaded and GC is restarted
398 // will raise an error in from_ in case of problem 395 // will raise an error in from_ in case of problem
399 callOnStateCreate(U_, L, from_, LookupMode::LaneBody); 396 callOnStateCreate(U_, _L, from_, LookupMode::LaneBody);
400 397
401 STACK_CHECK(L, 0); 398 STACK_CHECK(_L, 0);
402 // after all this, register everything we find in our name<->function database 399 // after all this, register everything we find in our name<->function database
403 lua_pushglobaltable(L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack 400 lua_pushglobaltable(_L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack
404 STACK_CHECK(L, 1); 401 STACK_CHECK(_L, 1);
405 populate_func_lookup_table(L, -1, nullptr); 402 populate_func_lookup_table(_L, -1, nullptr);
406 403
407#if 1 && USE_DEBUG_SPEW() 404#if 1 && USE_DEBUG_SPEW()
408 // dump the lookup database contents 405 // dump the lookup database contents
409 kLookupRegKey.pushValue(L); // L: {} 406 kLookupRegKey.pushValue(_L); // L: {}
410 lua_pushnil(L); // L: {} nil 407 lua_pushnil(_L); // L: {} nil
411 while (lua_next(L, -2)) { // L: {} k v 408 while (lua_next(_L, -2)) { // L: {} k v
412 lua_getglobal(L, "print"); // L: {} k v print 409 lua_getglobal(_L, "print"); // L: {} k v print
413 int const indent{ U_->debugspewIndentDepth.load(std::memory_order_relaxed) }; 410 int const indent{ U_->debugspewIndentDepth.load(std::memory_order_relaxed) };
414 lua_pushlstring(L, DebugSpewIndentScope::debugspew_indent, indent); // L: {} k v print " " 411 lua_pushlstring(_L, DebugSpewIndentScope::debugspew_indent, indent); // L: {} k v print " "
415 lua_pushvalue(L, -4); // L: {} k v print " " k 412 lua_pushvalue(_L, -4); // L: {} k v print " " k
416 lua_pushvalue(L, -4); // L: {} k v print " " k v 413 lua_pushvalue(_L, -4); // L: {} k v print " " k v
417 lua_call(L, 3, 0); // L: {} k v 414 lua_call(_L, 3, 0); // L: {} k v
418 lua_pop(L, 1); // L: {} k 415 lua_pop(_L, 1); // L: {} k
419 } 416 }
420 lua_pop(L, 1); // L: {} 417 lua_pop(_L, 1); // L: {}
421#endif // USE_DEBUG_SPEW() 418#endif // USE_DEBUG_SPEW()
422 419
423 lua_pop(L, 1); 420 lua_pop(_L, 1);
424 STACK_CHECK(L, 0); 421 STACK_CHECK(_L, 0);
425 return L; 422 return _L;
426} 423}