Skip to content

Commit 2fd37e6

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 7d3fb4a commit 2fd37e6

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]) {
@@ -472,8 +474,8 @@ const struct ExportedFunction *module_resolve_function0(Module *mod, int import_
472474
if (LIKELY(found_module != NULL)) {
473475
int exported_label = module_search_exported_function(found_module, function_name_atom, arity, glb);
474476
if (exported_label == 0) {
475-
char buf[256];
476-
atom_write_mfa(buf, 256, module_name_atom, function_name_atom, arity);
477+
char buf[MAX_MFA_NAME_LEN];
478+
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);
477479
fprintf(stderr, "Warning: function %s cannot be resolved.\n", buf);
478480
return NULL;
479481
}

src/libAtomVM/nifs.c

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@
6464
#include "zlib.h"
6565
#endif
6666

67-
#define MAX_NIF_NAME_LEN 260
6867
#define FLOAT_BUF_SIZE 64
6968

7069
#define RAISE(a, b) \
@@ -941,30 +940,11 @@ DEFINE_MATH_NIF(tanh)
941940
#include "nifs_hash.h"
942941
#pragma GCC diagnostic pop
943942

944-
const struct Nif *nifs_get(AtomString module, AtomString function, int arity)
943+
const struct Nif *nifs_get(const char *mfa)
945944
{
946-
char nifname[MAX_NIF_NAME_LEN];
947-
948-
int module_name_len = atom_string_len(module);
949-
memcpy(nifname, atom_string_data(module), module_name_len);
950-
951-
nifname[module_name_len] = ':';
952-
953-
int function_name_len = atom_string_len(function);
954-
if (UNLIKELY((arity > 9) || (module_name_len + function_name_len + 4 > MAX_NIF_NAME_LEN))) {
955-
// In AtomVM NIFs are limited to 9 parameters
956-
return NULL;
957-
}
958-
memcpy(nifname + module_name_len + 1, atom_string_data(function), function_name_len);
959-
960-
//TODO: handle NIFs with more than 9 parameters
961-
nifname[module_name_len + function_name_len + 1] = '/';
962-
nifname[module_name_len + function_name_len + 2] = '0' + arity;
963-
nifname[module_name_len + function_name_len + 3] = 0;
964-
965-
const NifNameAndNifPtr *nameAndPtr = nif_in_word_set(nifname, strlen(nifname));
945+
const NifNameAndNifPtr *nameAndPtr = nif_in_word_set(mfa, strlen(mfa));
966946
if (!nameAndPtr) {
967-
return platform_nifs_get_nif(nifname);
947+
return platform_nifs_get_nif(mfa);
968948
}
969949

970950
return nameAndPtr->nif;
@@ -3886,16 +3866,22 @@ static term nif_erlang_function_exported(Context *ctx, int argc, term argv[])
38863866
VALIDATE_VALUE(function, term_is_atom);
38873867
VALIDATE_VALUE(arity_term, term_is_integer);
38883868

3889-
AtomString module_name = globalcontext_atomstring_from_term(ctx->global, module);
3890-
AtomString function_name = globalcontext_atomstring_from_term(ctx->global, function);
3869+
atom_index_t module_name_ix = term_to_atom_index(module);
3870+
AtomString module_name = atom_table_get_atom_string(ctx->global->atom_table, module_name_ix);
3871+
atom_index_t function_name_ix = term_to_atom_index(function);
3872+
AtomString function_name = atom_table_get_atom_string(ctx->global->atom_table, function_name_ix);
3873+
38913874
avm_int_t arity = term_to_int(arity_term);
38923875

3893-
const struct ExportedFunction *bif = bif_registry_get_handler(module_name, function_name, arity);
3876+
char mfa[MAX_MFA_NAME_LEN];
3877+
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);
3878+
3879+
const struct ExportedFunction *bif = bif_registry_get_handler(mfa);
38943880
if (bif) {
38953881
return TRUE_ATOM;
38963882
}
38973883

3898-
struct Nif *nif = (struct Nif *) nifs_get(module_name, function_name, arity);
3884+
struct Nif *nif = (struct Nif *) nifs_get(mfa);
38993885
if (nif) {
39003886
return TRUE_ATOM;
39013887
}

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
@@ -1698,7 +1698,9 @@ term make_fun(Context *ctx, const Module *mod, int fun_index, term argv[])
16981698
static bool maybe_call_native(Context *ctx, AtomString module_name, AtomString function_name, int arity,
16991699
term *return_value)
17001700
{
1701-
const struct ExportedFunction *exported_bif = bif_registry_get_handler(module_name, function_name, arity);
1701+
char mfa[MAX_MFA_NAME_LEN];
1702+
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);
1703+
const struct ExportedFunction *exported_bif = bif_registry_get_handler(mfa);
17021704
if (exported_bif) {
17031705
if (exported_bif->type == GCBIFFunctionType) {
17041706
const struct GCBif *gcbif = EXPORTED_FUNCTION_TO_GCBIF(exported_bif);
@@ -1735,7 +1737,7 @@ static bool maybe_call_native(Context *ctx, AtomString module_name, AtomString f
17351737
}
17361738
}
17371739

1738-
struct Nif *nif = (struct Nif *) nifs_get(module_name, function_name, arity);
1740+
struct Nif *nif = (struct Nif *) nifs_get(mfa);
17391741
if (nif) {
17401742
*return_value = nif->nif_ptr(ctx, arity, ctx->x);
17411743
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)