diff options
Diffstat (limited to 'src/state.cpp')
-rw-r--r-- | src/state.cpp | 133 |
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 | ||
161 | static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_, char const* name_, size_t len_) | 158 | static 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) |
197 | static void copy_one_time_settings(Universe* U_, SourceState L1_, DestState L2_) | 194 | static 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 | ||
249 | lua_State* create_state([[maybe_unused]] Universe* U_, lua_State* from_) | 246 | lua_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 | */ |
322 | lua_State* luaG_newstate(Universe* U_, SourceState from_, char const* libs_) | 319 | lua_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 | } |