Skip to content

Commit bf82ba3

Browse files
committed
Factorize mfa as a key logic
Update signature of `atom_write_mfa` so it takes atom length and data separately to prepare for longer atoms. Signed-off-by: Paul Guyot <pguyot@kallisys.net>
1 parent 4190cd3 commit bf82ba3

File tree

9 files changed

+41
-48
lines changed

9 files changed

+41
-48
lines changed

src/libAtomVM/atom.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,19 +87,17 @@ static void utoa10(unsigned int int_value, char *integer_string)
8787
integer_string[integer_string_len] = '\0';
8888
}
8989

90-
void atom_write_mfa(char *buf, size_t buf_size, AtomString module, AtomString function, unsigned int arity)
90+
void atom_write_mfa(char *buf, size_t buf_size, size_t module_name_len, const void *module_data, size_t function_name_len, const void *function_data, unsigned int arity)
9191
{
92-
size_t module_name_len = atom_string_len(module);
93-
memcpy(buf, atom_string_data(module), module_name_len);
92+
memcpy(buf, module_data, module_name_len);
9493

9594
buf[module_name_len] = ':';
9695

97-
size_t function_name_len = atom_string_len(function);
9896
if (UNLIKELY((module_name_len + 1 + function_name_len + 1 + 4 + 1 > buf_size))) {
9997
fprintf(stderr, "Insufficient room to write mfa.\n");
10098
AVM_ABORT();
10199
}
102-
memcpy(buf + module_name_len + 1, atom_string_data(function), function_name_len);
100+
memcpy(buf + module_name_len + 1, function_data, function_name_len);
103101

104102
buf[module_name_len + function_name_len + 1] = '/';
105103
utoa10(arity, buf + module_name_len + 1 + function_name_len + 1);

src/libAtomVM/atom.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,13 @@ static inline const void *atom_string_data(AtomString atom_str)
9999
* buffer size.
100100
* @param buf the buffer to write into
101101
* @param buf_size the amount of room in the buffer
102-
* @param module the module name
103-
* @param function the function name
102+
* @param module_name_len length of the module name
103+
* @param module_data the module name
104+
* @param function_name_len length of the function name
105+
* @param function_data the function name
104106
* @param arity the function arity
105107
*/
106-
void atom_write_mfa(char *buf, size_t buf_size, AtomString module, AtomString function, unsigned int arity);
108+
void atom_write_mfa(char *buf, size_t buf_size, size_t module_name_len, const void *module_data, size_t function_name_len, const void *function_data, unsigned int arity);
107109

108110
#ifdef __cplusplus
109111
}

src/libAtomVM/bif.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,9 @@
5959
RAISE_ERROR_BIF(fail_label, BADARG_ATOM); \
6060
}
6161

62-
const struct ExportedFunction *bif_registry_get_handler(AtomString module, AtomString function, int arity)
62+
const struct ExportedFunction *bif_registry_get_handler(const char *mfa)
6363
{
64-
char bifname[MAX_BIF_NAME_LEN];
65-
66-
atom_write_mfa(bifname, MAX_BIF_NAME_LEN, module, function, arity);
67-
const BifNameAndPtr *nameAndPtr = in_word_set(bifname, strlen(bifname));
64+
const BifNameAndPtr *nameAndPtr = in_word_set(mfa, strlen(mfa));
6865
if (!nameAndPtr) {
6966
return NULL;
7067
}

src/libAtomVM/bif.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ extern "C" {
3939

4040
#define MAX_BIF_NAME_LEN 260
4141

42-
const struct ExportedFunction *bif_registry_get_handler(AtomString module, AtomString function, int arity);
42+
const struct ExportedFunction *bif_registry_get_handler(const char *mfa);
4343

4444
term bif_erlang_self_0(Context *ctx);
4545
term bif_erlang_node_0(Context *ctx);

src/libAtomVM/module.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,15 @@ static enum ModuleLoadResult module_build_imported_functions_table(Module *this_
123123
AtomString module_atom = module_get_atom_string_by_id(this_module, local_module_atom_index, glb);
124124
AtomString function_atom = module_get_atom_string_by_id(this_module, local_function_atom_index, glb);
125125
uint32_t arity = READ_32_UNALIGNED(table_data + i * 12 + 8 + 12);
126+
char mfa[MAX_MFA_NAME_LEN];
127+
atom_write_mfa(mfa, sizeof(mfa), atom_string_len(module_atom), atom_string_data(module_atom), atom_string_len(function_atom), atom_string_data(function_atom), arity);
126128

127-
const struct ExportedFunction *bif = bif_registry_get_handler(module_atom, function_atom, arity);
129+
const struct ExportedFunction *bif = bif_registry_get_handler(mfa);
128130

129131
if (bif) {
130132
this_module->imported_funcs[i] = bif;
131133
} else {
132-
this_module->imported_funcs[i] = &nifs_get(module_atom, function_atom, arity)->base;
134+
this_module->imported_funcs[i] = &nifs_get(mfa)->base;
133135
}
134136

135137
if (!this_module->imported_funcs[i]) {
@@ -473,8 +475,8 @@ const struct ExportedFunction *module_resolve_function0(Module *mod, int import_
473475
if (LIKELY(found_module != NULL)) {
474476
int exported_label = module_search_exported_function(found_module, function_name_atom, arity, glb);
475477
if (exported_label == 0) {
476-
char buf[256];
477-
atom_write_mfa(buf, 256, module_name_atom, function_name_atom, arity);
478+
char buf[MAX_MFA_NAME_LEN];
479+
atom_write_mfa(buf, sizeof(buf), atom_string_len(module_name_atom), atom_string_data(module_name_atom), atom_string_len(function_name_atom), atom_string_data(function_name_atom), arity);
478480
fprintf(stderr, "Warning: function %s cannot be resolved.\n", buf);
479481
return NULL;
480482
}

src/libAtomVM/nifs.c

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@
6161
#include "unicode.h"
6262
#include "utils.h"
6363

64-
#define MAX_NIF_NAME_LEN 260
6564
#define FLOAT_BUF_SIZE 64
6665

6766
#define RAISE(a, b) \
@@ -909,30 +908,11 @@ DEFINE_MATH_NIF(tanh)
909908
#include "nifs_hash.h"
910909
#pragma GCC diagnostic pop
911910

912-
const struct Nif *nifs_get(AtomString module, AtomString function, int arity)
911+
const struct Nif *nifs_get(const char *mfa)
913912
{
914-
char nifname[MAX_NIF_NAME_LEN];
915-
916-
int module_name_len = atom_string_len(module);
917-
memcpy(nifname, atom_string_data(module), module_name_len);
918-
919-
nifname[module_name_len] = ':';
920-
921-
int function_name_len = atom_string_len(function);
922-
if (UNLIKELY((arity > 9) || (module_name_len + function_name_len + 4 > MAX_NIF_NAME_LEN))) {
923-
// In AtomVM NIFs are limited to 9 parameters
924-
return NULL;
925-
}
926-
memcpy(nifname + module_name_len + 1, atom_string_data(function), function_name_len);
927-
928-
//TODO: handle NIFs with more than 9 parameters
929-
nifname[module_name_len + function_name_len + 1] = '/';
930-
nifname[module_name_len + function_name_len + 2] = '0' + arity;
931-
nifname[module_name_len + function_name_len + 3] = 0;
932-
933-
const NifNameAndNifPtr *nameAndPtr = nif_in_word_set(nifname, strlen(nifname));
913+
const NifNameAndNifPtr *nameAndPtr = nif_in_word_set(mfa, strlen(mfa));
934914
if (!nameAndPtr) {
935-
return platform_nifs_get_nif(nifname);
915+
return platform_nifs_get_nif(mfa);
936916
}
937917

938918
return nameAndPtr->nif;
@@ -3599,16 +3579,22 @@ static term nif_erlang_function_exported(Context *ctx, int argc, term argv[])
35993579
VALIDATE_VALUE(function, term_is_atom);
36003580
VALIDATE_VALUE(arity_term, term_is_integer);
36013581

3602-
AtomString module_name = globalcontext_atomstring_from_term(ctx->global, module);
3603-
AtomString function_name = globalcontext_atomstring_from_term(ctx->global, function);
3582+
atom_index_t module_name_ix = term_to_atom_index(module);
3583+
AtomString module_name = atom_table_get_atom_string(ctx->global->atom_table, module_name_ix);
3584+
atom_index_t function_name_ix = term_to_atom_index(function);
3585+
AtomString function_name = atom_table_get_atom_string(ctx->global->atom_table, function_name_ix);
3586+
36043587
avm_int_t arity = term_to_int(arity_term);
36053588

3606-
const struct ExportedFunction *bif = bif_registry_get_handler(module_name, function_name, arity);
3589+
char mfa[MAX_MFA_NAME_LEN];
3590+
atom_write_mfa(mfa, sizeof(mfa), atom_string_len(module_name), atom_string_data(module_name), atom_string_len(function_name), atom_string_data(function_name), arity);
3591+
3592+
const struct ExportedFunction *bif = bif_registry_get_handler(mfa);
36073593
if (bif) {
36083594
return TRUE_ATOM;
36093595
}
36103596

3611-
struct Nif *nif = (struct Nif *) nifs_get(module_name, function_name, arity);
3597+
struct Nif *nif = (struct Nif *) nifs_get(mfa);
36123598
if (nif) {
36133599
return TRUE_ATOM;
36143600
}

src/libAtomVM/nifs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ extern "C" {
4646
ctx->x[1] = (error_type_atom); \
4747
return term_invalid_term();
4848

49-
const struct Nif *nifs_get(AtomString module, AtomString function, int arity);
49+
const struct Nif *nifs_get(const char *mfa);
5050

5151
// spawn opt is used by distribution nifs
5252
term nif_erlang_spawn_opt(Context *ctx, int argc, term argv[]);

src/libAtomVM/opcodesswitch.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1692,7 +1692,9 @@ term make_fun(Context *ctx, const Module *mod, int fun_index, term argv[])
16921692
static bool maybe_call_native(Context *ctx, AtomString module_name, AtomString function_name, int arity,
16931693
term *return_value)
16941694
{
1695-
const struct ExportedFunction *exported_bif = bif_registry_get_handler(module_name, function_name, arity);
1695+
char mfa[MAX_MFA_NAME_LEN];
1696+
atom_write_mfa(mfa, sizeof(mfa), atom_string_len(module_name), atom_string_data(module_name), atom_string_len(function_name), atom_string_data(function_name), arity);
1697+
const struct ExportedFunction *exported_bif = bif_registry_get_handler(mfa);
16961698
if (exported_bif) {
16971699
if (exported_bif->type == GCBIFFunctionType) {
16981700
const struct GCBif *gcbif = EXPORTED_FUNCTION_TO_GCBIF(exported_bif);
@@ -1729,7 +1731,7 @@ static bool maybe_call_native(Context *ctx, AtomString module_name, AtomString f
17291731
}
17301732
}
17311733

1732-
struct Nif *nif = (struct Nif *) nifs_get(module_name, function_name, arity);
1734+
struct Nif *nif = (struct Nif *) nifs_get(mfa);
17331735
if (nif) {
17341736
*return_value = nif->nif_ptr(ctx, arity, ctx->x);
17351737
return true;

src/libAtomVM/term_typedef.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,10 @@ typedef union {
144144
avm_float_t f;
145145
} float_term_t;
146146

147+
// Quite a low value, BEAM is 255 + 255 + 1 + strlen(max(arity))
148+
// This buffer is typically allocated on C stack
149+
// This is a hard limit for bifs and nifs. It currently is only used for
150+
// printing error messages for other functions.
151+
#define MAX_MFA_NAME_LEN 260
152+
147153
#endif

0 commit comments

Comments
 (0)