Skip to content

Commit f26daf0

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 ed89914 commit f26daf0

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
@@ -58,12 +58,9 @@
5858
RAISE_ERROR_BIF(fail_label, BADARG_ATOM); \
5959
}
6060

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

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_byte_size_1(Context *ctx, uint32_t fail_label, int live, term arg1);

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_ALIGNED(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
@@ -58,7 +58,6 @@
5858
#include "unicode.h"
5959
#include "utils.h"
6060

61-
#define MAX_NIF_NAME_LEN 260
6261
#define FLOAT_BUF_SIZE 64
6362

6463
#define RAISE(a, b) \
@@ -873,30 +872,11 @@ DEFINE_MATH_NIF(tanh)
873872
#include "nifs_hash.h"
874873
#pragma GCC diagnostic pop
875874

876-
const struct Nif *nifs_get(AtomString module, AtomString function, int arity)
875+
const struct Nif *nifs_get(const char *mfa)
877876
{
878-
char nifname[MAX_NIF_NAME_LEN];
879-
880-
int module_name_len = atom_string_len(module);
881-
memcpy(nifname, atom_string_data(module), module_name_len);
882-
883-
nifname[module_name_len] = ':';
884-
885-
int function_name_len = atom_string_len(function);
886-
if (UNLIKELY((arity > 9) || (module_name_len + function_name_len + 4 > MAX_NIF_NAME_LEN))) {
887-
// In AtomVM NIFs are limited to 9 parameters
888-
return NULL;
889-
}
890-
memcpy(nifname + module_name_len + 1, atom_string_data(function), function_name_len);
891-
892-
//TODO: handle NIFs with more than 9 parameters
893-
nifname[module_name_len + function_name_len + 1] = '/';
894-
nifname[module_name_len + function_name_len + 2] = '0' + arity;
895-
nifname[module_name_len + function_name_len + 3] = 0;
896-
897-
const NifNameAndNifPtr *nameAndPtr = nif_in_word_set(nifname, strlen(nifname));
877+
const NifNameAndNifPtr *nameAndPtr = nif_in_word_set(mfa, strlen(mfa));
898878
if (!nameAndPtr) {
899-
return platform_nifs_get_nif(nifname);
879+
return platform_nifs_get_nif(mfa);
900880
}
901881

902882
return nameAndPtr->nif;
@@ -3476,16 +3456,22 @@ static term nif_erlang_function_exported(Context *ctx, int argc, term argv[])
34763456
VALIDATE_VALUE(function, term_is_atom);
34773457
VALIDATE_VALUE(arity_term, term_is_integer);
34783458

3479-
AtomString module_name = globalcontext_atomstring_from_term(ctx->global, module);
3480-
AtomString function_name = globalcontext_atomstring_from_term(ctx->global, function);
3459+
atom_index_t module_name_ix = term_to_atom_index(module);
3460+
AtomString module_name = atom_table_get_atom_string(ctx->global->atom_table, module_name_ix);
3461+
atom_index_t function_name_ix = term_to_atom_index(function);
3462+
AtomString function_name = atom_table_get_atom_string(ctx->global->atom_table, function_name_ix);
3463+
34813464
avm_int_t arity = term_to_int(arity_term);
34823465

3483-
const struct ExportedFunction *bif = bif_registry_get_handler(module_name, function_name, arity);
3466+
char mfa[MAX_MFA_NAME_LEN];
3467+
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);
3468+
3469+
const struct ExportedFunction *bif = bif_registry_get_handler(mfa);
34843470
if (bif) {
34853471
return TRUE_ATOM;
34863472
}
34873473

3488-
struct Nif *nif = (struct Nif *) nifs_get(module_name, function_name, arity);
3474+
struct Nif *nif = (struct Nif *) nifs_get(mfa);
34893475
if (nif) {
34903476
return TRUE_ATOM;
34913477
}

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
#ifdef __cplusplus
5252
}

src/libAtomVM/opcodesswitch.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,7 +1606,9 @@ term make_fun(Context *ctx, const Module *mod, int fun_index, term argv[])
16061606
static bool maybe_call_native(Context *ctx, AtomString module_name, AtomString function_name, int arity,
16071607
term *return_value)
16081608
{
1609-
const struct ExportedFunction *exported_bif = bif_registry_get_handler(module_name, function_name, arity);
1609+
char mfa[MAX_MFA_NAME_LEN];
1610+
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);
1611+
const struct ExportedFunction *exported_bif = bif_registry_get_handler(mfa);
16101612
if (exported_bif) {
16111613
if (exported_bif->type == GCBIFFunctionType) {
16121614
const struct GCBif *gcbif = EXPORTED_FUNCTION_TO_GCBIF(exported_bif);
@@ -1643,7 +1645,7 @@ static bool maybe_call_native(Context *ctx, AtomString module_name, AtomString f
16431645
}
16441646
}
16451647

1646-
struct Nif *nif = (struct Nif *) nifs_get(module_name, function_name, arity);
1648+
struct Nif *nif = (struct Nif *) nifs_get(mfa);
16471649
if (nif) {
16481650
*return_value = nif->nif_ptr(ctx, arity, ctx->x);
16491651
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)