Skip to content

Commit a7ee8b4

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 79045db commit a7ee8b4

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
@@ -117,13 +117,15 @@ static enum ModuleLoadResult module_build_imported_functions_table(Module *this_
117117
AtomString module_atom = module_get_atom_string_by_id(this_module, local_module_atom_index, glb);
118118
AtomString function_atom = module_get_atom_string_by_id(this_module, local_function_atom_index, glb);
119119
uint32_t arity = READ_32_UNALIGNED(table_data + i * 12 + 8 + 12);
120+
char mfa[MAX_MFA_NAME_LEN];
121+
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);
120122

121-
const struct ExportedFunction *bif = bif_registry_get_handler(module_atom, function_atom, arity);
123+
const struct ExportedFunction *bif = bif_registry_get_handler(mfa);
122124

123125
if (bif) {
124126
this_module->imported_funcs[i] = bif;
125127
} else {
126-
this_module->imported_funcs[i] = &nifs_get(module_atom, function_atom, arity)->base;
128+
this_module->imported_funcs[i] = &nifs_get(mfa)->base;
127129
}
128130

129131
if (!this_module->imported_funcs[i]) {
@@ -435,8 +437,8 @@ const struct ExportedFunction *module_resolve_function0(Module *mod, int import_
435437
if (LIKELY(found_module != NULL)) {
436438
int exported_label = module_search_exported_function(found_module, function_name_atom, arity, glb);
437439
if (exported_label == 0) {
438-
char buf[256];
439-
atom_write_mfa(buf, 256, module_name_atom, function_name_atom, arity);
440+
char buf[MAX_MFA_NAME_LEN];
441+
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);
440442
fprintf(stderr, "Warning: function %s cannot be resolved.\n", buf);
441443
return NULL;
442444
}

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;
@@ -3610,16 +3590,22 @@ static term nif_erlang_function_exported(Context *ctx, int argc, term argv[])
36103590
VALIDATE_VALUE(function, term_is_atom);
36113591
VALIDATE_VALUE(arity_term, term_is_integer);
36123592

3613-
AtomString module_name = globalcontext_atomstring_from_term(ctx->global, module);
3614-
AtomString function_name = globalcontext_atomstring_from_term(ctx->global, function);
3593+
atom_index_t module_name_ix = term_to_atom_index(module);
3594+
AtomString module_name = atom_table_get_atom_string(ctx->global->atom_table, module_name_ix);
3595+
atom_index_t function_name_ix = term_to_atom_index(function);
3596+
AtomString function_name = atom_table_get_atom_string(ctx->global->atom_table, function_name_ix);
3597+
36153598
avm_int_t arity = term_to_int(arity_term);
36163599

3617-
const struct ExportedFunction *bif = bif_registry_get_handler(module_name, function_name, arity);
3600+
char mfa[MAX_MFA_NAME_LEN];
3601+
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);
3602+
3603+
const struct ExportedFunction *bif = bif_registry_get_handler(mfa);
36183604
if (bif) {
36193605
return TRUE_ATOM;
36203606
}
36213607

3622-
struct Nif *nif = (struct Nif *) nifs_get(module_name, function_name, arity);
3608+
struct Nif *nif = (struct Nif *) nifs_get(mfa);
36233609
if (nif) {
36243610
return TRUE_ATOM;
36253611
}

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
@@ -1665,7 +1665,9 @@ term make_fun(Context *ctx, const Module *mod, int fun_index, term argv[])
16651665
static bool maybe_call_native(Context *ctx, AtomString module_name, AtomString function_name, int arity,
16661666
term *return_value)
16671667
{
1668-
const struct ExportedFunction *exported_bif = bif_registry_get_handler(module_name, function_name, arity);
1668+
char mfa[MAX_MFA_NAME_LEN];
1669+
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);
1670+
const struct ExportedFunction *exported_bif = bif_registry_get_handler(mfa);
16691671
if (exported_bif) {
16701672
if (exported_bif->type == GCBIFFunctionType) {
16711673
const struct GCBif *gcbif = EXPORTED_FUNCTION_TO_GCBIF(exported_bif);
@@ -1702,7 +1704,7 @@ static bool maybe_call_native(Context *ctx, AtomString module_name, AtomString f
17021704
}
17031705
}
17041706

1705-
struct Nif *nif = (struct Nif *) nifs_get(module_name, function_name, arity);
1707+
struct Nif *nif = (struct Nif *) nifs_get(mfa);
17061708
if (nif) {
17071709
*return_value = nif->nif_ptr(ctx, arity, ctx->x);
17081710
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)