Skip to content

Commit

Permalink
AP_Scripting: dynamically load some binding objects
Browse files Browse the repository at this point in the history
Only create the binding object (singleton metatable/userdata or C
function reference) once the user first references a particular
singleton or userdata creation function. Once created, the object is
stored into the script's environment so it doesn't get recreated on the
next reference and there isn't any further overhead. The userdatas are
no longer shared between scripts which imposes a slight memory penalty
for multiple scripts using the same singleton but this avoids an
additional lookup time cost.

Userdata and ap_objects aren't eligible for this optimization as the C++
code might want a particular metatable at any time.

Saves ~9.3K Lua heap.
  • Loading branch information
tpwrules committed Jul 5, 2024
1 parent 2fcb295 commit b414c6b
Showing 1 changed file with 39 additions and 19 deletions.
58 changes: 39 additions & 19 deletions libraries/AP_Scripting/generator/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2499,6 +2499,43 @@ void emit_loaders(void) {
emit_type_index(parsed_singletons, "singleton");
emit_type_index(parsed_ap_objects, "ap_object");

fprintf(source, "static int binding_index(lua_State *L) {\n");
fprintf(source, " const char * name = luaL_checkstring(L, 2);\n");
fprintf(source, "\n");
fprintf(source, " bool found = false;\n");
fprintf(source, " for (uint32_t i = 0; i < ARRAY_SIZE(singleton_fun); i++) {\n");
fprintf(source, " if (strcmp(name, singleton_fun[i].name) == 0) {\n");
fprintf(source, " lua_newuserdata(L, 0);\n");
fprintf(source, " if (luaL_newmetatable(L, name)) { // need to create metatable\n");
fprintf(source, " lua_pushcfunction(L, singleton_fun[i].func);\n");
fprintf(source, " lua_setfield(L, -2, \"__index\");\n");
fprintf(source, " }\n");
fprintf(source, " lua_setmetatable(L, -2);\n");
fprintf(source, " found = true;\n");
fprintf(source, " break;\n");
fprintf(source, " }\n");
fprintf(source, " }\n");
fprintf(source, " if (!found) {\n");
fprintf(source, " for (uint32_t i = 0; i < ARRAY_SIZE(new_userdata); i++) {\n");
fprintf(source, " if (strcmp(name, new_userdata[i].name) == 0) {\n");
fprintf(source, " lua_pushcfunction(L, new_userdata[i].fun);\n");
fprintf(source, " found = true;\n");
fprintf(source, " break;\n");
fprintf(source, " }\n");
fprintf(source, " }\n");
fprintf(source, " }\n");
fprintf(source, " if (!found) {\n");
fprintf(source, " return 0;\n");
fprintf(source, " }\n");
fprintf(source, "\n");
fprintf(source, " // store found value to avoid a re-index\n");
fprintf(source, " lua_pushvalue(L, -2);\n");
fprintf(source, " lua_pushvalue(L, -2);\n");
fprintf(source, " lua_settable(L, -5);\n");
fprintf(source, "\n");
fprintf(source, " return 1;\n");
fprintf(source, "}\n\n");

fprintf(source, "void load_generated_bindings(lua_State *L) {\n");
fprintf(source, " luaL_checkstack(L, 5, \"Out of stack\");\n"); // this is more stack space then we need, but should never fail
fprintf(source, " // userdata metatables\n");
Expand All @@ -2525,24 +2562,7 @@ void emit_loaders(void) {
fprintf(source, " }\n");
fprintf(source, "\n");

fprintf(source, " // singleton metatables\n");
fprintf(source, " for (uint32_t i = 0; i < ARRAY_SIZE(singleton_fun); i++) {\n");
fprintf(source, " lua_newuserdata(L, 0);\n");
fprintf(source, " luaL_newmetatable(L, singleton_fun[i].name);\n");
fprintf(source, " lua_pushcfunction(L, singleton_fun[i].func);\n");
fprintf(source, " lua_setfield(L, -2, \"__index\");\n");

fprintf(source, " lua_setmetatable(L, -2);\n");
fprintf(source, " lua_setglobal(L, singleton_fun[i].name);\n");
fprintf(source, " }\n");
fprintf(source, "\n");

fprintf(source, " // userdata creation funcs\n");
fprintf(source, " for (uint32_t i = 0; i < ARRAY_SIZE(new_userdata); i++) {\n");
fprintf(source, " lua_pushcfunction(L, new_userdata[i].fun);\n");
fprintf(source, " lua_setglobal(L, new_userdata[i].name);\n");
fprintf(source, " }\n");
fprintf(source, "\n");
fprintf(source, " // singletons and userdata creation funcs are loaded dynamically\n");

fprintf(source, "}\n\n");
}
Expand Down Expand Up @@ -2601,7 +2621,7 @@ void emit_userdata_new_funcs(void) {
void emit_sandbox(void) {
fprintf(source, "void load_generated_sandbox(lua_State *L) {\n");
fprintf(source, " lua_createtable(L, 0, 1);\n");
fprintf(source, " lua_pushglobaltable(L);\n");
fprintf(source, " lua_pushcfunction(L, binding_index);\n");
fprintf(source, " lua_setfield(L, -2, \"__index\");\n");
fprintf(source, " lua_setmetatable(L, -2);\n");
fprintf(source, "}\n");
Expand Down

0 comments on commit b414c6b

Please sign in to comment.