Skip to content

Commit 4190cd3

Browse files
committed
Introduce atom_index_t type
`atom_index_t` type represents a valid atom index. Signature of functions that returned an atom index that could be an error were modified consequently, introducing a type for the error results of `atom_table_ensure_atoms` and `atom_table_ensure_atom` and removing now redundant `globalcontext_insert_atom` in favor of `globalcontext_make_atom` that returns a term. Signed-off-by: Paul Guyot <pguyot@kallisys.net>
1 parent 59a314c commit 4190cd3

File tree

20 files changed

+427
-286
lines changed

20 files changed

+427
-286
lines changed

src/libAtomVM/atom.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ extern "C" {
4545
#define ATOM_STR(LENSTR, STR) (LENSTR STR)
4646

4747
typedef const void *AtomString;
48+
typedef uint32_t atom_index_t;
4849

4950
/**
5051
* @brief Gets a C string from an AtomString

src/libAtomVM/atom_table.c

Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ struct HNode
5050
{
5151
struct HNode *next;
5252
AtomString key;
53-
long index;
53+
atom_index_t index;
5454
};
5555

5656
struct HNodeGroup
5757
{
5858
struct HNodeGroup *next;
59-
long first_index;
59+
atom_index_t first_index;
6060
uint16_t len;
6161

6262
struct HNode nodes[];
@@ -188,29 +188,16 @@ static inline struct HNode *get_node(const struct AtomTable *hash_table, AtomStr
188188
return get_node_with_hash(hash_table, string, hash);
189189
}
190190

191-
long atom_table_get_index(struct AtomTable *table, AtomString string)
192-
{
193-
unsigned long hash = sdbm_hash(string, atom_string_len(string));
194-
195-
SMP_RDLOCK(table);
196-
197-
struct HNode *node = get_node_with_hash(table, string, hash);
198-
long result = (node != NULL) ? node->index : ATOM_TABLE_NOT_FOUND;
199-
200-
SMP_UNLOCK(table);
201-
return result;
202-
}
203-
204191
// TODO: this function needs use an efficient structure such as a skip list
205-
static struct HNode *get_node_using_index(struct AtomTable *table, long index)
192+
static struct HNode *get_node_using_index(struct AtomTable *table, atom_index_t index)
206193
{
207194
if (UNLIKELY(((size_t) index) >= table->count)) {
208195
return NULL;
209196
}
210197

211198
struct HNodeGroup *node_group = table->first_node_group;
212199
while (node_group) {
213-
long first_index = node_group->first_index;
200+
atom_index_t first_index = node_group->first_index;
214201
if (first_index + node_group->len > index) {
215202
return &node_group->nodes[index - first_index];
216203
}
@@ -221,7 +208,7 @@ static struct HNode *get_node_using_index(struct AtomTable *table, long index)
221208
return NULL;
222209
}
223210

224-
AtomString atom_table_get_atom_string(struct AtomTable *table, long index)
211+
AtomString atom_table_get_atom_string(struct AtomTable *table, atom_index_t index)
225212
{
226213
SMP_RDLOCK(table);
227214

@@ -264,7 +251,7 @@ int atom_table_cmp_using_atom_index(struct AtomTable *table, int t_atom_index, i
264251
return memcmp_result;
265252
}
266253

267-
atom_ref_t atom_table_get_atom_ptr_and_len(struct AtomTable *table, long index, size_t *out_len)
254+
atom_ref_t atom_table_get_atom_ptr_and_len(struct AtomTable *table, atom_index_t index, size_t *out_len)
268255
{
269256
SMP_RDLOCK(table);
270257

@@ -334,10 +321,10 @@ static inline void insert_node_into_bucket(
334321
node->next = maybe_existing_node;
335322
}
336323

337-
static inline long insert_node(struct AtomTable *table, struct HNodeGroup *node_group,
324+
static inline atom_index_t insert_node(struct AtomTable *table, struct HNodeGroup *node_group,
338325
unsigned long bucket_index, AtomString string)
339326
{
340-
long new_index = table->count;
327+
atom_index_t new_index = table->count;
341328
table->count++;
342329

343330
struct HNode *node = &node_group->nodes[new_index - node_group->first_index];
@@ -398,7 +385,7 @@ static inline bool maybe_rehash(struct AtomTable *table, int new_entries)
398385
return do_rehash(table, new_capacity);
399386
}
400387

401-
long atom_table_ensure_atom(struct AtomTable *table, AtomString string, enum AtomTableCopyOpt opts)
388+
enum AtomTableEnsureAtomResult atom_table_ensure_atom(struct AtomTable *table, AtomString string, enum AtomTableCopyOpt opts, atom_index_t *result)
402389
{
403390
unsigned long hash = sdbm_hash(string, atom_string_len(string));
404391
SMP_WRLOCK(table);
@@ -407,19 +394,20 @@ long atom_table_ensure_atom(struct AtomTable *table, AtomString string, enum Ato
407394
struct HNode *node = get_node_from_bucket(table, bucket_index, string);
408395
if (node) {
409396
SMP_UNLOCK(table);
410-
return node->index;
397+
*result = node->index;
398+
return AtomTableEnsureAtomOk;
411399
}
412400
if (opts & AtomTableAlreadyExisting) {
413401
SMP_UNLOCK(table);
414-
return ATOM_TABLE_NOT_FOUND;
402+
return AtomTableEnsureAtomNotFound;
415403
}
416404

417405
struct HNodeGroup *node_group = table->last_node_group;
418406
if (!table->last_node_group_avail) {
419407
node_group = new_node_group(table, DEFAULT_SIZE);
420408
if (IS_NULL_PTR(node_group)) {
421409
SMP_UNLOCK(table);
422-
return ATOM_TABLE_ALLOC_FAIL;
410+
return AtomTableEnsureAtomAllocFail;
423411
}
424412
}
425413

@@ -429,7 +417,7 @@ long atom_table_ensure_atom(struct AtomTable *table, AtomString string, enum Ato
429417
uint8_t *buf = malloc(1 + len);
430418
if (IS_NULL_PTR(buf)) {
431419
SMP_UNLOCK(table);
432-
return ATOM_TABLE_ALLOC_FAIL;
420+
return AtomTableEnsureAtomAllocFail;
433421
}
434422
memcpy(buf, string, 1 + len);
435423
maybe_copied = buf;
@@ -439,10 +427,10 @@ long atom_table_ensure_atom(struct AtomTable *table, AtomString string, enum Ato
439427
bucket_index = hash % table->capacity;
440428
}
441429

442-
long new_index = insert_node(table, node_group, bucket_index, maybe_copied);
430+
*result = insert_node(table, node_group, bucket_index, maybe_copied);
443431

444432
SMP_UNLOCK(table);
445-
return new_index;
433+
return AtomTableEnsureAtomOk;
446434
}
447435

448436
static inline int read_encoded_len(const uint8_t **len_bytes)
@@ -463,8 +451,11 @@ static inline int read_encoded_len(const uint8_t **len_bytes)
463451
}
464452
}
465453

466-
int atom_table_ensure_atoms(struct AtomTable *table, const void *atoms, int count,
467-
int *translate_table, enum EnsureAtomsOpt opt)
454+
// -1 is not a valid atom index as we're limited to 2^20
455+
#define ATOM_TABLE_NOT_FOUND_MARKER ((atom_index_t) -1)
456+
457+
enum AtomTableEnsureAtomResult atom_table_ensure_atoms(struct AtomTable *table, const void *atoms, int count,
458+
atom_index_t *translate_table, enum EnsureAtomsOpt opt)
468459
{
469460
bool is_long_format = (opt & EnsureLongEncoding) != 0;
470461

@@ -481,7 +472,7 @@ int atom_table_ensure_atoms(struct AtomTable *table, const void *atoms, int coun
481472
if (UNLIKELY(atom_len < 0)) {
482473
fprintf(stderr, "Found invalid atom len.");
483474
SMP_UNLOCK(table);
484-
return ATOM_TABLE_INVALID_LEN;
475+
return AtomTableEnsureAtomInvalidLen;
485476
} else if (UNLIKELY(atom_len > 255)) {
486477
fprintf(stderr,
487478
"Unsupported atom length %i bytes.\n"
@@ -491,7 +482,7 @@ int atom_table_ensure_atoms(struct AtomTable *table, const void *atoms, int coun
491482
"https://github.com/atomvm/AtomVM/issues\n",
492483
atom_len);
493484
SMP_UNLOCK(table);
494-
return ATOM_TABLE_INVALID_LEN;
485+
return AtomTableEnsureAtomInvalidLen;
495486
}
496487
char tmp_old_fmt[256];
497488
tmp_old_fmt[0] = atom_len;
@@ -508,7 +499,7 @@ int atom_table_ensure_atoms(struct AtomTable *table, const void *atoms, int coun
508499
translate_table[i] = node->index;
509500
} else {
510501
new_atoms_count++;
511-
translate_table[i] = ATOM_TABLE_NOT_FOUND;
502+
translate_table[i] = ATOM_TABLE_NOT_FOUND_MARKER;
512503
}
513504
}
514505

@@ -531,12 +522,12 @@ int atom_table_ensure_atoms(struct AtomTable *table, const void *atoms, int coun
531522
next_atom += 1 + atom_len;
532523
}
533524

534-
if (translate_table[i] == ATOM_TABLE_NOT_FOUND) {
525+
if (translate_table[i] == ATOM_TABLE_NOT_FOUND_MARKER) {
535526
if (!table->last_node_group_avail) {
536527
node_group = new_node_group(table, remaining_atoms);
537528
if (IS_NULL_PTR(node_group)) {
538529
SMP_UNLOCK(table);
539-
return ATOM_TABLE_ALLOC_FAIL;
530+
return AtomTableEnsureAtomAllocFail;
540531
}
541532
}
542533

@@ -545,7 +536,7 @@ int atom_table_ensure_atoms(struct AtomTable *table, const void *atoms, int coun
545536
if (IS_NULL_PTR(atom_copy)) {
546537
// we are not going to remove atoms that have already been added up to this one
547538
SMP_UNLOCK(table);
548-
return ATOM_TABLE_ALLOC_FAIL;
539+
return AtomTableEnsureAtomAllocFail;
549540
}
550541
atom_copy[0] = atom_len;
551542
memcpy(atom_copy + 1, to_be_copied, atom_len);
@@ -566,5 +557,5 @@ int atom_table_ensure_atoms(struct AtomTable *table, const void *atoms, int coun
566557

567558
SMP_UNLOCK(table);
568559

569-
return 0;
560+
return AtomTableEnsureAtomOk;
570561
}

src/libAtomVM/atom_table.h

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,12 @@
2424
#include <stdbool.h>
2525

2626
#include "atom.h"
27+
#include "utils.h"
2728

2829
#ifdef __cplusplus
2930
extern "C" {
3031
#endif
3132

32-
#define ATOM_TABLE_NOT_FOUND -1
33-
#define ATOM_TABLE_ALLOC_FAIL -2
34-
#define ATOM_TABLE_INVALID_LEN -3
35-
3633
struct AtomTable;
3734

3835
enum EnsureAtomsOpt
@@ -48,27 +45,33 @@ enum AtomTableCopyOpt
4845
AtomTableAlreadyExisting = 2
4946
};
5047

48+
enum AtomTableEnsureAtomResult
49+
{
50+
AtomTableEnsureAtomOk = 0,
51+
AtomTableEnsureAtomNotFound = -1,
52+
AtomTableEnsureAtomAllocFail = -2,
53+
AtomTableEnsureAtomInvalidLen = -3,
54+
};
55+
5156
typedef const void *atom_ref_t;
5257

5358
struct AtomTable *atom_table_new();
5459
void atom_table_destroy(struct AtomTable *table);
5560

5661
size_t atom_table_count(struct AtomTable *table);
5762

58-
long atom_table_ensure_atom(struct AtomTable *table, AtomString string, enum AtomTableCopyOpt opts);
63+
enum AtomTableEnsureAtomResult atom_table_ensure_atom(struct AtomTable *table, AtomString string, enum AtomTableCopyOpt opts, atom_index_t *result) MUST_CHECK;
5964

6065
// This function is deprecated and it will be removed.
6166
// atom strings should be copied to caller owned buffers.
62-
AtomString atom_table_get_atom_string(struct AtomTable *table, long index);
63-
64-
long atom_table_get_index(struct AtomTable *table, AtomString string);
67+
AtomString atom_table_get_atom_string(struct AtomTable *table, atom_index_t index);
6568

66-
int atom_table_ensure_atoms(struct AtomTable *table, const void *atoms, int count,
67-
int *translate_table, enum EnsureAtomsOpt opts);
69+
enum AtomTableEnsureAtomResult atom_table_ensure_atoms(struct AtomTable *table, const void *atoms, int count,
70+
atom_index_t *translate_table, enum EnsureAtomsOpt opts) MUST_CHECK;
6871

6972
int atom_table_cmp_using_atom_index(
7073
struct AtomTable *table, int t_atom_index, int other_atom_index);
71-
atom_ref_t atom_table_get_atom_ptr_and_len(struct AtomTable *table, long index, size_t *out_len);
74+
atom_ref_t atom_table_get_atom_ptr_and_len(struct AtomTable *table, atom_index_t index, size_t *out_len);
7275
bool atom_table_is_atom_ref_ascii(struct AtomTable *table, atom_ref_t atom);
7376
void atom_table_write_bytes(struct AtomTable *table, atom_ref_t atom, size_t buf_len, void *outbuf);
7477
void atom_table_write_cstring(

src/libAtomVM/bif.c

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "overflow_helpers.h"
3232
#include "smp.h"
3333
#include "term.h"
34+
#include "term_typedef.h"
3435
#include "trace.h"
3536
#include "unicode.h"
3637
#include "utils.h"
@@ -1729,16 +1730,25 @@ static term list_to_atom(Context *ctx, term a_list, bool create_new, term *error
17291730
if (!create_new) {
17301731
atom_opts |= AtomTableAlreadyExisting;
17311732
}
1732-
long global_atom_index = atom_table_ensure_atom(ctx->global->atom_table, atom, atom_opts);
1733+
atom_index_t global_atom_index;
1734+
enum AtomTableEnsureAtomResult ensure_result = atom_table_ensure_atom(ctx->global->atom_table, atom, atom_opts, &global_atom_index);
17331735
free((void *) atom);
1734-
if (UNLIKELY(global_atom_index == ATOM_TABLE_NOT_FOUND)) {
1735-
*error_reason = BADARG_ATOM;
1736-
return term_invalid_term();
1737-
} else if (UNLIKELY(global_atom_index == ATOM_TABLE_ALLOC_FAIL)) {
1738-
*error_reason = OUT_OF_MEMORY_ATOM;
1739-
return term_invalid_term();
1736+
switch (ensure_result) {
1737+
case AtomTableEnsureAtomNotFound:
1738+
case AtomTableEnsureAtomInvalidLen: {
1739+
*error_reason = BADARG_ATOM;
1740+
return term_invalid_term();
1741+
}
1742+
case AtomTableEnsureAtomAllocFail: {
1743+
*error_reason = OUT_OF_MEMORY_ATOM;
1744+
return term_invalid_term();
1745+
}
1746+
case AtomTableEnsureAtomOk: {
1747+
return term_from_atom_index(global_atom_index);
1748+
}
1749+
default:
1750+
UNREACHABLE();
17401751
}
1741-
return term_from_atom_index(global_atom_index);
17421752
}
17431753

17441754
term bif_erlang_binary_to_atom_2(Context *ctx, uint32_t fail_label, int live, term arg1, term arg2)
@@ -1829,14 +1839,23 @@ term binary_to_atom(Context *ctx, term a_binary, term encoding, bool create_new,
18291839
if (!create_new) {
18301840
atom_opts |= AtomTableAlreadyExisting;
18311841
}
1832-
long global_atom_index = atom_table_ensure_atom(ctx->global->atom_table, atom, atom_opts);
1842+
atom_index_t global_atom_index;
1843+
enum AtomTableEnsureAtomResult ensure_result = atom_table_ensure_atom(ctx->global->atom_table, atom, atom_opts, &global_atom_index);
18331844
free((void *) atom);
1834-
if (UNLIKELY(global_atom_index == ATOM_TABLE_NOT_FOUND)) {
1835-
*error_reason = BADARG_ATOM;
1836-
return term_invalid_term();
1837-
} else if (UNLIKELY(global_atom_index == ATOM_TABLE_ALLOC_FAIL)) {
1838-
*error_reason = OUT_OF_MEMORY_ATOM;
1839-
return term_invalid_term();
1845+
switch (ensure_result) {
1846+
case AtomTableEnsureAtomNotFound:
1847+
case AtomTableEnsureAtomInvalidLen: {
1848+
*error_reason = BADARG_ATOM;
1849+
return term_invalid_term();
1850+
}
1851+
case AtomTableEnsureAtomAllocFail: {
1852+
*error_reason = OUT_OF_MEMORY_ATOM;
1853+
return term_invalid_term();
1854+
}
1855+
case AtomTableEnsureAtomOk: {
1856+
return term_from_atom_index(global_atom_index);
1857+
}
1858+
default:
1859+
UNREACHABLE();
18401860
}
1841-
return term_from_atom_index(global_atom_index);
18421861
}

src/libAtomVM/defaultatoms.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
*/
2020

2121
#include "defaultatoms.h"
22+
#include "term.h"
2223

2324
#include <stdlib.h>
2425
#include <string.h>
@@ -38,12 +39,13 @@ void defaultatoms_init(GlobalContext *glb)
3839
};
3940
#undef X
4041

41-
for (int i = 0; i < PLATFORM_ATOMS_BASE_INDEX; i++) {
42+
for (size_t i = 0; i < PLATFORM_ATOMS_BASE_INDEX; i++) {
4243
if (UNLIKELY((size_t) atoms[i][0] != strlen(atoms[i] + 1))) {
4344
AVM_ABORT();
4445
}
4546

46-
if (UNLIKELY(globalcontext_insert_atom(glb, atoms[i]) != i)) {
47+
term atom_term = globalcontext_make_atom(glb, atoms[i]);
48+
if (UNLIKELY(term_to_atom_index(atom_term) != i)) {
4749
AVM_ABORT();
4850
}
4951
}

0 commit comments

Comments
 (0)