-
Notifications
You must be signed in to change notification settings - Fork 130
Implement code:get_object_code/1 nif #1814
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Implement code:get_object_code/1 nif #1814
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code must compile first, after that there are some changes that are required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a small change that is still required. Also, "Run tests with BEAM" is really important for us, so CI must be green also for all those tests.
What we got:
Raised {badmatch,error}, stacktrace:
[{test_code_get_object_code,get_object_from_export_test_module,0,
[{file,"/Users/runner/work/AtomVM/AtomVM/tests/erlang_tests/test_code_get_object_code.erl"},
{line,52}]},
{test_code_get_object_code,start,0,
test_code_get_object_code:
test_code_get_object_code:FAILED
[{file,"/Users/runner/work/AtomVM/AtomVM/tests/erlang_tests/test_code_get_object_code.erl"},
{line,28}]},
{erl_eval,do_apply,7,[{file,"erl_eval.erl"},{line,746}]},
{erl_eval,try_clauses,10,[{file,"erl_eval.erl"},{line,1052}]},
{erl_eval,expr,6,[{file,"erl_eval.erl"},{line,494}]},
{erl_eval,exprs,6,[{file,"erl_eval.erl"},{line,136}]},
{init,start_it,1,[]},
{init,start_em,1,[]}]
src/libAtomVM/nifs.c
Outdated
| const uint8_t *filename; | ||
| size_t filename_len; | ||
| uint32_t line; | ||
| if (LIKELY(module_find_line(module, module->line_refs_offsets[0], &line, &filename_len, &filename))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This requires debug information to be available, that it is frequently true, but not mandatory. And making this function work according to debug info availability might be counter intuitive.
If you know module name, you can just return module_name <> ".beam".
This is not 100% correct, but the correct solution would be tracking where the file has been loaded from, and standardizing how to refer to .beam files stored into .avm, that is some other work (not that much).
So I suggest leaving a TODO that just says that code has to be changed to return the complete path, not just the beam file name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK, code:get_object_code/1 returns the path of the beam when it was loaded into the VM, which is unrelated to whatever path is stored in the beam itself. We can start with ModuleName ++ ".beam" (it's not a binary but a list), and if it adds anything useful, we could at some point put the path of the avm or the partition.
I also wonder if we really need this nif and if returning error is not sufficient. It seems that BEAM returns error if a module is loaded from a binary with code:load_binary/3 and doesn't return the path passed to this function (which is what I would have expected).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the code according to beam behaviour.
It seems like only either code:add_path or initial module loading causes code:get_object_code to return the tuple, otherwise it returns error.
I think we had to implement this function for popcorn needs because some of the stdlib modules used it to check if there is a loaded module as far as i remember.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CI is still failing since code is not compiling on certain platforms / compiler versions due to some missing cast. Let's fix build error and squash everything.
This is the compile error I'm talking about:
[ 2%] Building C object src/platforms/generic_unix/libAtomVM/CMakeFiles/libAtomVM.dir/nifs.c.o
/home/runner/work/AtomVM/AtomVM/src/libAtomVM/nifs.c:5379:43: error: passing 'char *' to parameter of type 'const uint8_t *' (aka 'const unsigned char *') converts between pointers to integer types where one is of the unique plain 'char' type and the other is not [-Werror,-Wpointer-sign]
5379 | term filename_term = term_from_string(module_file_name, filename_len, &ctx->heap);
| ^~~~~~~~~~~~~~~~
/home/runner/work/AtomVM/AtomVM/src/libAtomVM/term.h:1747:52: note: passing argument to parameter 'data' here
1747 | static inline term term_from_string(const uint8_t *data, uint16_t size, Heap *heap)
| ^
1 error generated.
23036aa to
0d96986
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything looks good, let's do git commit --amend --signoff so DCO CI step will be green as well.
981c5e6 to
c4bc515
Compare
…et-object-code Implement code:get_object_code/1 nif These changes are made under both the "Apache 2.0" and the "GNU Lesser General Public License 2.1 or later" license terms (dual license). SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
src/libAtomVM/nifs.c
Outdated
| } | ||
| memcpy(module_file_name, module_name, module_name_len); | ||
| memcpy(module_file_name + module_name_len, ".beam", 6); | ||
| Module *module = globalcontext_load_module_from_avm(ctx->global, module_file_name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use globalcontext_get_module instead as here you are replacing the existing module with another copy. We don't support hot code reloading yet and bad things definitely happens when JIT is enabled. But even if we did, we don't want to reload a new module everytime this nif is called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is that OTP version of get_object_code function checks for the loaded code in the file system. Thats why the test:
get_object_from_export_test_module() ->
Bin = ?EXPORT_TEST_MODULE_DATA,
error = code:get_object_code(export_test_module),
{module, export_test_module} = code:load_binary(
export_test_module, "export_test_module.beam", Bin
),
{module, export_test_module} = code:ensure_loaded(export_test_module),
error = code:get_object_code(export_test_module),
24 = export_test_module:exported_func(4),
ok.
fails on error = code:get_object_code(export_test_module), in AVM (badmatch) for modules loaded with code:load_binary/3.
The same test is successful in beam.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I skip BEAM testing for this one, or rather implement sys_get_module_file (which would try to open beam file in file system) function in every sys.c (+ sys.h) and use it in get_object_code/1?
c4bc515 to
8160928
Compare
These changes are made under both the "Apache 2.0" and the "GNU Lesser General
Public License 2.1 or later" license terms (dual license).
SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
These changes are made under both the "Apache 2.0" and the "GNU Lesser General
Public License 2.1 or later" license terms (dual license).
SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later