From 21599ec58c4fa8ebcd3f7c23eab62aa269fc8e77 Mon Sep 17 00:00:00 2001
From: Alexander Turenko <alexander.turenko@tarantool.org>
Date: Tue, 17 Jan 2023 22:31:52 +0300
Subject: [PATCH] box/lua: eliminate luaL_register*() usages in box

The idea of the refactoring is described in a previous commit.

The change is straightforward:

* Use `luaL_findtable()` to find/create a nested table in `_G`.
* Use `luaL_setfuncs()` to assign functions to a table.
* Use `luaT_newmodule()` to register a module for `require()`.

`require('box.internal.<...>')` calls are replaced with
`box.internal.<...>`, because `box` submodules are not registered as
modules anymore (IOW, are not placed into `package.loaded`).

However `_G.box == require('box')`, it remains unchanged.

One may wonder why fourth argument of `luaL_findtable()` (size hint for
the hash part of the table) is always zero in the added calls. It is an
effect of the following points:

* Those calls are not on hot paths and, moreover, there is no sense to
  use `luaL_findtable()` with a string literal as the second argument on
  a hot path (no sense to parse the string literal in runtime if a
  performance is the goal).
* Using `lengthof()` macro would add more code to read for a human (the
  argument itself, a line carry to fit 80 symbols, an inclusion of
  trivia/util.h) at no gain.
* A hardcoded array length is a developer's stress factor: it looks like
  it requires an update at a change of the array. So zero is better.

Part of #7774

NO_DOC=user visible behavior is unchanged, pure refactoring change
NO_TEST=see NO_DOC
NO_CHANGELOG=see NO_DOC
---
 src/box/lua/call.c       |  3 ++-
 src/box/lua/cfg.cc       |  3 ++-
 src/box/lua/console.c    |  2 +-
 src/box/lua/console.lua  |  5 ++---
 src/box/lua/ctl.c        |  3 ++-
 src/box/lua/error.cc     |  9 +++------
 src/box/lua/index.c      |  9 +++------
 src/box/lua/info.c       | 11 +++--------
 src/box/lua/init.c       | 13 +++++++++----
 src/box/lua/key_def.c    |  2 +-
 src/box/lua/lib.c        |  3 ++-
 src/box/lua/load_cfg.lua |  2 +-
 src/box/lua/merger.c     |  2 +-
 src/box/lua/misc.cc      |  3 ++-
 src/box/lua/net_box.c    |  8 +-------
 src/box/lua/net_box.lua  |  3 +--
 src/box/lua/schema.lua   |  2 +-
 src/box/lua/sequence.c   |  3 ++-
 src/box/lua/session.c    |  6 ++++--
 src/box/lua/space.cc     |  3 ++-
 src/box/lua/stat.c       | 28 +++++++++-------------------
 src/box/lua/tuple.c      |  5 +++--
 src/box/lua/tuple.lua    |  2 +-
 src/box/lua/xlog.c       |  2 +-
 24 files changed, 59 insertions(+), 73 deletions(-)

diff --git a/src/box/lua/call.c b/src/box/lua/call.c
index 4ae531dad2..a2d7b9e3a2 100644
--- a/src/box/lua/call.c
+++ b/src/box/lua/call.c
@@ -1145,7 +1145,8 @@ box_lua_call_init(struct lua_State *L)
 	trigger_add(&luaL_msgpack_default->on_update,
 		    &call_serializer_no_error_ext.update_trigger);
 
-	luaL_register(L, "box.internal", boxlib_internal);
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.internal", 0);
+	luaL_setfuncs(L, boxlib_internal, 0);
 	lua_pop(L, 1);
 	/*
 	 * Register the trigger that will push persistent
diff --git a/src/box/lua/cfg.cc b/src/box/lua/cfg.cc
index 947a3a6a78..38ed523915 100644
--- a/src/box/lua/cfg.cc
+++ b/src/box/lua/cfg.cc
@@ -483,6 +483,7 @@ box_lua_cfg_init(struct lua_State *L)
 		{NULL, NULL}
 	};
 
-	luaL_register(L, "box.internal", cfglib_internal);
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.internal", 0);
+	luaL_setfuncs(L, cfglib_internal, 0);
 	lua_pop(L, 1);
 }
diff --git a/src/box/lua/console.c b/src/box/lua/console.c
index 6bc9067b0b..0facfb09ce 100644
--- a/src/box/lua/console.c
+++ b/src/box/lua/console.c
@@ -886,7 +886,7 @@ tarantool_lua_console_init(struct lua_State *L)
 		{"run_on_eval",		lbox_console_run_on_eval},
 		{NULL, NULL}
 	};
-	luaL_register_module(L, "console", consolelib);
+	luaT_newmodule(L, "console", consolelib);
 
 	/* readline() func needs a ref to completion_handler (in upvalue) */
 	lua_getfield(L, -1, "completion_handler");
diff --git a/src/box/lua/console.lua b/src/box/lua/console.lua
index be1e8d2d3b..403ceaea85 100644
--- a/src/box/lua/console.lua
+++ b/src/box/lua/console.lua
@@ -18,7 +18,7 @@ ffi.cdef[[
 ]]
 
 local internal = require('console')
-local session_internal = require('box.internal.session')
+local session_internal = box.internal.session
 local fiber = require('fiber')
 local socket = require('socket')
 local log = require('log')
@@ -26,7 +26,6 @@ local errno = require('errno')
 local urilib = require('uri')
 local yaml = require('yaml')
 local net_box = require('net.box')
-local box_internal = require('box.internal')
 local help = require('help').help
 
 local DEFAULT_CONNECT_TIMEOUT = 10
@@ -199,7 +198,7 @@ local function current_output()
 end
 
 -- Used by console_session_push.
-box_internal.format_lua_push = function(value)
+box.internal.format_lua_push = function(value)
     local internal_opts = gen_lua_opts(current_output()["opts"])
     value = format_lua_value(true, internal_opts, value)
     return '-- Push\n' .. value .. ';'
diff --git a/src/box/lua/ctl.c b/src/box/lua/ctl.c
index 40d5ae4f28..ad075fc7ba 100644
--- a/src/box/lua/ctl.c
+++ b/src/box/lua/ctl.c
@@ -166,6 +166,7 @@ static const struct luaL_Reg lbox_ctl_lib[] = {
 void
 box_lua_ctl_init(struct lua_State *L)
 {
-	luaL_register_module(L, "box.ctl", lbox_ctl_lib);
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.ctl", 0);
+	luaL_setfuncs(L, lbox_ctl_lib, 0);
 	lua_pop(L, 1);
 }
diff --git a/src/box/lua/error.cc b/src/box/lua/error.cc
index 54ec28468c..8e922e4466 100644
--- a/src/box/lua/error.cc
+++ b/src/box/lua/error.cc
@@ -293,10 +293,7 @@ lbox_errinj_info(struct lua_State *L)
 
 void
 box_lua_error_init(struct lua_State *L) {
-	static const struct luaL_Reg errorlib[] = {
-		{NULL, NULL}
-	};
-	luaL_register_module(L, "box.error", errorlib);
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.error", 0);
 	for (int i = 0; i < box_error_code_MAX; i++) {
 		const char *name = box_error_codes[i].errstr;
 		if (strstr(name, "UNUSED") || strstr(name, "RESERVED"))
@@ -340,7 +337,7 @@ box_lua_error_init(struct lua_State *L) {
 		{"get", lbox_errinj_get},
 		{NULL, NULL}
 	};
-	/* box.error.injection is not set by register_module */
-	luaL_register_module(L, "box.error.injection", errinjlib);
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.error.injection", 0);
+	luaL_setfuncs(L, errinjlib, 0);
 	lua_pop(L, 1);
 }
diff --git a/src/box/lua/index.c b/src/box/lua/index.c
index 5c2351991a..fcbc17ff33 100644
--- a/src/box/lua/index.c
+++ b/src/box/lua/index.c
@@ -365,12 +365,8 @@ box_lua_index_init(struct lua_State *L)
 	CTID_STRUCT_ITERATOR_PTR = luaL_ctypeid(L, "struct iterator*");
 	assert(CTID_STRUCT_ITERATOR_PTR != 0);
 
-	static const struct luaL_Reg indexlib [] = {
-		{NULL, NULL}
-	};
-
 	/* box.index */
-	luaL_register_module(L, "box.index", indexlib);
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.index", 0);
 	box_index_init_iterator_types(L, -2);
 	lua_pop(L, 1);
 
@@ -393,6 +389,7 @@ box_lua_index_init(struct lua_State *L)
 		{NULL, NULL}
 	};
 
-	luaL_register(L, "box.internal", boxlib_internal);
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.internal", 0);
+	luaL_setfuncs(L, boxlib_internal, 0);
 	lua_pop(L, 1);
 }
diff --git a/src/box/lua/info.c b/src/box/lua/info.c
index b007081fa3..0e08b3004f 100644
--- a/src/box/lua/info.c
+++ b/src/box/lua/info.c
@@ -757,19 +757,14 @@ lbox_info_call(struct lua_State *L)
 void
 box_lua_info_init(struct lua_State *L)
 {
-	static const struct luaL_Reg infolib [] = {
-		{NULL, NULL}
-	};
-
-	luaL_register_module(L, "box.info", infolib);
-
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.info", 0);
 	lua_newtable(L);		/* metatable for info */
 
 	lua_pushstring(L, "__index");
 
 	lua_newtable(L); /* table for __index */
-	luaL_register(L, NULL, lbox_info_dynamic_meta);
-	luaL_register(L, NULL, lbox_info_dynamic_meta_v16);
+	luaL_setfuncs(L, lbox_info_dynamic_meta, 0);
+	luaL_setfuncs(L, lbox_info_dynamic_meta_v16, 0);
 	lua_pushcclosure(L, lbox_info_index, 1);
 	lua_settable(L, -3);
 
diff --git a/src/box/lua/init.c b/src/box/lua/init.c
index 750f004f78..98960f2195 100644
--- a/src/box/lua/init.c
+++ b/src/box/lua/init.c
@@ -517,11 +517,16 @@ box_lua_init(struct lua_State *L)
 	CTID_STRUCT_TXN_SAVEPOINT_PTR = luaL_ctypeid(L,
 						     "struct txn_savepoint*");
 
-	/* Use luaL_register() to set _G.box */
-	luaL_register(L, "box", boxlib);
-	lua_pop(L, 1);
+	/*
+	 * Create a table and expose it as require('box') and
+	 * as _G.box.
+	 */
+	luaT_newmodule(L, "box", boxlib);
+	lua_setfield(L, LUA_GLOBALSINDEX, "box");
 
-	luaL_register(L, "box.backup", boxlib_backup);
+	/* box.backup = {<...>} */
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.backup", 0);
+	luaL_setfuncs(L, boxlib_backup, 0);
 	lua_pop(L, 1);
 
 	box_lua_error_init(L);
diff --git a/src/box/lua/key_def.c b/src/box/lua/key_def.c
index 321bdad3f8..e5fc370e49 100644
--- a/src/box/lua/key_def.c
+++ b/src/box/lua/key_def.c
@@ -517,6 +517,6 @@ luaopen_key_def(struct lua_State *L)
 		{"totable", lbox_key_def_to_table},
 		{NULL, NULL}
 	};
-	luaL_register_module(L, "key_def", meta);
+	luaT_newmodule(L, "key_def", meta);
 	return 1;
 }
diff --git a/src/box/lua/lib.c b/src/box/lua/lib.c
index 3d45f4ce1d..f0921074d6 100644
--- a/src/box/lua/lib.c
+++ b/src/box/lua/lib.c
@@ -578,7 +578,8 @@ box_lua_lib_init(struct lua_State *L)
 		{ "load",		lbox_module_load	},
 		{ NULL, NULL },
 	};
-	luaL_register(L, "box.lib", top_methods);
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.lib", 0);
+	luaL_setfuncs(L, top_methods, 0);
 	lua_pop(L, 1);
 
 	static const struct luaL_Reg lbox_module_methods[] = {
diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua
index 9535a735a4..8909a82875 100644
--- a/src/box/lua/load_cfg.lua
+++ b/src/box/lua/load_cfg.lua
@@ -2,7 +2,7 @@
 
 local log = require('log')
 local json = require('json')
-local private = require('box.internal')
+local private = box.internal
 local urilib = require('uri')
 local math = require('math')
 local fiber = require('fiber')
diff --git a/src/box/lua/merger.c b/src/box/lua/merger.c
index ad21f4b7cf..5985c63ceb 100644
--- a/src/box/lua/merger.c
+++ b/src/box/lua/merger.c
@@ -1288,7 +1288,7 @@ luaopen_merger(struct lua_State *L)
 		{"new", lbox_merger_new},
 		{NULL, NULL}
 	};
-	luaL_register_module(L, "merger", meta);
+	luaT_newmodule(L, "merger", meta);
 
 	/* Add internal.{select,ipairs}(). */
 	lua_newtable(L); /* merger.internal */
diff --git a/src/box/lua/misc.cc b/src/box/lua/misc.cc
index 720267e438..a338c44432 100644
--- a/src/box/lua/misc.cc
+++ b/src/box/lua/misc.cc
@@ -432,7 +432,8 @@ box_lua_misc_init(struct lua_State *L)
 		{NULL, NULL}
 	};
 
-	luaL_register(L, "box.internal", boxlib_internal);
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.internal", 0);
+	luaL_setfuncs(L, boxlib_internal, 0);
 	lua_pop(L, 1);
 
 	int rc = luaL_cdef(L, "struct tuple_format;");
diff --git a/src/box/lua/net_box.c b/src/box/lua/net_box.c
index 307057f12c..5075894fe5 100644
--- a/src/box/lua/net_box.c
+++ b/src/box/lua/net_box.c
@@ -3041,12 +3041,6 @@ luaopen_net_box(struct lua_State *L)
 		{ "new_transport",  luaT_netbox_new_transport },
 		{ NULL, NULL}
 	};
-	/* luaL_register_module polutes _G */
-	lua_newtable(L);
-	luaL_openlib(L, NULL, net_box_lib, 0);
-	lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
-	lua_pushvalue(L, -2);
-	lua_setfield(L, -2, "net.box.lib");
-	lua_remove(L, -1);
+	luaT_newmodule(L, "net.box.lib", net_box_lib);
 	return 1;
 }
diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua
index c74156081a..6c57ad5392 100644
--- a/src/box/lua/net_box.lua
+++ b/src/box/lua/net_box.lua
@@ -1302,8 +1302,7 @@ this_module.self = {
         check_call_args(args)
         args = args or {}
         proc_name = tostring(proc_name)
-        local status, proc, obj = pcall(package.loaded['box.internal'].
-            call_loadproc, proc_name)
+        local status, proc, obj = pcall(box.internal.call_loadproc, proc_name)
         if not status then
             rollback()
             return error(proc) -- re-throw
diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index 20685bfb7a..95363aca32 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -7,7 +7,7 @@ local log = require('log')
 local buffer = require('buffer')
 local fiber = require('fiber')
 local session = box.session
-local internal = require('box.internal')
+local internal = box.internal
 local utf8 = require('utf8')
 local function setmap(table)
     return setmetatable(table, { __serialize = 'map' })
diff --git a/src/box/lua/sequence.c b/src/box/lua/sequence.c
index bf0714c1a1..f5d5a456cc 100644
--- a/src/box/lua/sequence.c
+++ b/src/box/lua/sequence.c
@@ -178,7 +178,8 @@ box_lua_sequence_init(struct lua_State *L)
 		{"reset", lbox_sequence_reset},
 		{NULL, NULL}
 	};
-	luaL_register(L, "box.internal.sequence", sequence_internal_lib);
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.internal.sequence", 0);
+	luaL_setfuncs(L, sequence_internal_lib, 0);
 	lua_pop(L, 1);
 
 	static struct trigger on_alter_sequence_in_lua;
diff --git a/src/box/lua/session.c b/src/box/lua/session.c
index 23581ef328..2145fc9e28 100644
--- a/src/box/lua/session.c
+++ b/src/box/lua/session.c
@@ -544,7 +544,8 @@ box_lua_session_init(struct lua_State *L)
 		{"run_on_auth", lbox_session_run_on_auth},
 		{NULL, NULL}
 	};
-	luaL_register(L, "box.internal.session", session_internal_lib);
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.internal.session", 0);
+	luaL_setfuncs(L, session_internal_lib, 0);
 	lua_pop(L, 1);
 
 	static const struct luaL_Reg sessionlib[] = {
@@ -566,7 +567,8 @@ box_lua_session_init(struct lua_State *L)
 		{"push", lbox_session_push},
 		{NULL, NULL}
 	};
-	luaL_register_module(L, sessionlib_name, sessionlib);
+	luaL_findtable(L, LUA_GLOBALSINDEX, sessionlib_name, 0);
+	luaL_setfuncs(L, sessionlib, 0);
 	lbox_session_settings_init(L);
 	lua_pop(L, 1);
 }
diff --git a/src/box/lua/space.cc b/src/box/lua/space.cc
index ccd73e00db..688f6b969e 100644
--- a/src/box/lua/space.cc
+++ b/src/box/lua/space.cc
@@ -781,6 +781,7 @@ box_lua_space_init(struct lua_State *L)
 		{"frommap", lbox_space_frommap},
 		{NULL, NULL}
 	};
-	luaL_register(L, "box.internal.space", space_internal_lib);
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.internal.space", 0);
+	luaL_setfuncs(L, space_internal_lib, 0);
 	lua_pop(L, 1);
 }
diff --git a/src/box/lua/stat.c b/src/box/lua/stat.c
index edba974ab6..7f42d88f35 100644
--- a/src/box/lua/stat.c
+++ b/src/box/lua/stat.c
@@ -452,39 +452,29 @@ box_lua_stat_init(struct lua_State *L)
 		{NULL, NULL}
 	};
 
-	luaL_register_module(L, "box.stat", statlib);
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.stat", 0);
+	luaL_setfuncs(L, statlib, 0);
 
 	lua_newtable(L);
-	luaL_register(L, NULL, lbox_stat_meta);
+	luaL_setfuncs(L, lbox_stat_meta, 0);
 	lua_setmetatable(L, -2);
 	lua_pop(L, 1); /* stat module */
 
-	static const struct luaL_Reg netstatlib [] = {
-		{NULL, NULL}
-	};
-
-	luaL_register_module(L, "box.stat.net", netstatlib);
-
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.stat.net", 0);
 	lua_newtable(L);
-	luaL_register(L, NULL, lbox_stat_net_meta);
+	luaL_setfuncs(L, lbox_stat_net_meta, 0);
 	lua_setmetatable(L, -2);
 	lua_pop(L, 1); /* stat net module */
 
-	luaL_register_module(L, "box.stat.net.thread", netstatlib);
-
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.stat.net.thread", 0);
 	lua_newtable(L);
-	luaL_register(L, NULL, lbox_stat_net_thread_meta);
+	luaL_setfuncs(L, lbox_stat_net_thread_meta, 0);
 	lua_setmetatable(L, -2);
 	lua_pop(L, 1); /* stat net module */
 
-	static const struct luaL_Reg memtx_mvcc_statlib[] = {
-		{NULL, NULL}
-	};
-
-	luaL_register_module(L, "box.stat.memtx.tx", memtx_mvcc_statlib);
-
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.stat.memtx.tx", 0);
 	lua_newtable(L);
-	luaL_register(L, NULL, lbox_stat_memtx_mvcc_meta);
+	luaL_setfuncs(L, lbox_stat_memtx_mvcc_meta, 0);
 	lua_setmetatable(L, -2);
 	lua_pop(L, 1); /* stat tx module */
 
diff --git a/src/box/lua/tuple.c b/src/box/lua/tuple.c
index 6fd7fd42de..d19f57d735 100644
--- a/src/box/lua/tuple.c
+++ b/src/box/lua/tuple.c
@@ -740,12 +740,13 @@ box_lua_tuple_init(struct lua_State *L)
 	/* export C functions to Lua */
 	luaL_findtable(L, LUA_GLOBALSINDEX, "box.internal", 1);
 	luaL_newmetatable(L, tuplelib_name);
-	luaL_register(L, NULL, lbox_tuple_meta);
+	luaL_setfuncs(L, lbox_tuple_meta, 0);
 	lua_setfield(L, -2, "tuple");
 	lua_pop(L, 1); /* box.internal */
 	luaL_register_type(L, tuple_iteratorlib_name,
 			   lbox_tuple_iterator_meta);
-	luaL_register_module(L, tuplelib_name, lbox_tuplelib);
+	luaL_findtable(L, LUA_GLOBALSINDEX, tuplelib_name, 0);
+	luaL_setfuncs(L, lbox_tuplelib, 0);
 	lua_pop(L, 1);
 
 	tuple_serializer_update_options();
diff --git a/src/box/lua/tuple.lua b/src/box/lua/tuple.lua
index 98f3f8de63..33aa444849 100644
--- a/src/box/lua/tuple.lua
+++ b/src/box/lua/tuple.lua
@@ -4,7 +4,7 @@ local ffi = require('ffi')
 local msgpackffi = require('msgpackffi')
 local fun = require('fun')
 local buffer = require('buffer')
-local internal = require('box.internal')
+local internal = box.internal
 local cord_ibuf_take = buffer.internal.cord_ibuf_take
 local cord_ibuf_put = buffer.internal.cord_ibuf_put
 
diff --git a/src/box/lua/xlog.c b/src/box/lua/xlog.c
index 19679a7247..698e72fecd 100644
--- a/src/box/lua/xlog.c
+++ b/src/box/lua/xlog.c
@@ -328,7 +328,7 @@ box_lua_xlog_init(struct lua_State *L)
 	CTID_STRUCT_XLOG_CURSOR_REF = luaL_ctypeid(L, "struct xlog_cursor&");
 	assert(CTID_STRUCT_XLOG_CURSOR_REF != 0);
 
-	luaL_register_module(L, xloglib_name, lbox_xlog_parser_lib);
+	luaT_newmodule(L, xloglib_name, lbox_xlog_parser_lib);
 
 	lua_newtable(L);
 	lua_setmetatable(L, -2);
-- 
GitLab