Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 32 additions & 40 deletions src/libAtomVM/bif.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,10 @@
#define INT64_MAX_AS_AVM_FLOAT 9223372036854775295.0 // 0x43DFFFFFFFFFFFFF = 2^62 * 1.1...1b
#endif

// intn.h and term.h headers are decoupled. We check here that sign enum values are matching.
_Static_assert(
(int) TermPositiveInteger == (int) IntNPositiveInteger, "term/intn definition mismatch");
_Static_assert(
(int) TermNegativeInteger == (int) IntNNegativeInteger, "term/intn definition mismatch");

static term make_bigint(Context *ctx, uint32_t fail_label, uint32_t live,
const intn_digit_t bigres[], size_t bigres_len, intn_integer_sign_t sign);

static void term_to_bigint(term arg1, intn_digit_t *tmp_buf1, const intn_digit_t **b1,
static void conv_term_to_bigint(term arg1, intn_digit_t *tmp_buf1, const intn_digit_t **b1,
size_t *b1_len, intn_integer_sign_t *b1_sign);

const struct ExportedFunction *bif_registry_get_handler(const char *mfa)
Expand Down Expand Up @@ -555,11 +549,11 @@ static term add_maybe_bigint(Context *ctx, uint32_t fail_label, uint32_t live, t
const intn_digit_t *bn1;
size_t bn1_len;
intn_integer_sign_t bn1_sign;
term_to_bigint(arg1, tmp_buf1, &bn1, &bn1_len, &bn1_sign);
conv_term_to_bigint(arg1, tmp_buf1, &bn1, &bn1_len, &bn1_sign);
const intn_digit_t *bn2;
size_t bn2_len;
intn_integer_sign_t bn2_sign;
term_to_bigint(arg2, tmp_buf2, &bn2, &bn2_len, &bn2_sign);
conv_term_to_bigint(arg2, tmp_buf2, &bn2, &bn2_len, &bn2_sign);

size_t bigres_len = INTN_ADD_OUT_LEN(bn1_len, bn2_len);
if (bigres_len > INTN_MAX_RES_LEN) {
Expand Down Expand Up @@ -693,11 +687,11 @@ static term sub_maybe_bigint(Context *ctx, uint32_t fail_label, uint32_t live, t
const intn_digit_t *bn1;
size_t bn1_len;
intn_integer_sign_t bn1_sign;
term_to_bigint(arg1, tmp_buf1, &bn1, &bn1_len, &bn1_sign);
conv_term_to_bigint(arg1, tmp_buf1, &bn1, &bn1_len, &bn1_sign);
const intn_digit_t *bn2;
size_t bn2_len;
intn_integer_sign_t bn2_sign;
term_to_bigint(arg2, tmp_buf2, &bn2, &bn2_len, &bn2_sign);
conv_term_to_bigint(arg2, tmp_buf2, &bn2, &bn2_len, &bn2_sign);

size_t bigres_len = INTN_SUB_OUT_LEN(bn1_len, bn2_len);
if (bigres_len > INTN_MAX_RES_LEN) {
Expand Down Expand Up @@ -815,18 +809,17 @@ static term make_bigint(Context *ctx, uint32_t fail_label, uint32_t live,
if (!intn_fits_int64(bigres, count, sign)) {
size_t intn_data_size;
size_t rounded_res_len;
term_intn_to_term_size(count, &intn_data_size, &rounded_res_len);
term_bigint_size_requirements(count, &intn_data_size, &rounded_res_len);

if (UNLIKELY(memory_ensure_free_with_roots(
ctx, BOXED_INTN_SIZE(intn_data_size), live, ctx->x, MEMORY_CAN_SHRINK)
ctx, BOXED_BIGINT_HEAP_SIZE(intn_data_size), live, ctx->x, MEMORY_CAN_SHRINK)
!= MEMORY_GC_OK)) {
RAISE_ERROR_BIF(fail_label, OUT_OF_MEMORY_ATOM);
}

term bigres_term = term_create_uninitialized_intn(
term bigres_term = term_create_uninitialized_bigint(
intn_data_size, (term_integer_sign_t) sign, &ctx->heap);
intn_digit_t *dest_buf = (void *) term_intn_data(bigres_term);
intn_copy(bigres, count, dest_buf, rounded_res_len);
term_initialize_bigint(bigres_term, bigres, count, rounded_res_len);

return bigres_term;
} else {
Expand All @@ -839,14 +832,12 @@ static term make_bigint(Context *ctx, uint32_t fail_label, uint32_t live,
}
}

static void term_to_bigint(term arg1, intn_digit_t *tmp_buf1, const intn_digit_t **b1,
static void conv_term_to_bigint(term arg1, intn_digit_t *tmp_buf1, const intn_digit_t **b1,
size_t *b1_len, intn_integer_sign_t *b1_sign)
{
if (term_is_boxed_integer(arg1)
&& (term_boxed_size(arg1) > (INTN_INT64_LEN * sizeof(intn_digit_t)) / sizeof(term))) {
*b1 = term_intn_data(arg1);
*b1_len = term_intn_size(arg1) * (sizeof(term) / sizeof(intn_digit_t));
*b1_sign = (intn_integer_sign_t) term_boxed_integer_sign(arg1);
if (term_is_bigint(arg1)) {
term_to_bigint(arg1, b1, b1_len, b1_sign);

} else {
avm_int64_t i64 = term_maybe_unbox_int64(arg1);
intn_from_int64(i64, tmp_buf1, b1_sign);
Expand Down Expand Up @@ -874,11 +865,11 @@ static term mul_maybe_bigint(Context *ctx, uint32_t fail_label, uint32_t live, t
const intn_digit_t *bn1;
size_t bn1_len;
intn_integer_sign_t bn1_sign;
term_to_bigint(arg1, tmp_buf1, &bn1, &bn1_len, &bn1_sign);
conv_term_to_bigint(arg1, tmp_buf1, &bn1, &bn1_len, &bn1_sign);
const intn_digit_t *bn2;
size_t bn2_len;
intn_integer_sign_t bn2_sign;
term_to_bigint(arg2, tmp_buf2, &bn2, &bn2_len, &bn2_sign);
conv_term_to_bigint(arg2, tmp_buf2, &bn2, &bn2_len, &bn2_sign);

size_t bigres_len = INTN_MUL_OUT_LEN(bn1_len, bn2_len);
if (bigres_len > INTN_MAX_RES_LEN) {
Expand Down Expand Up @@ -1038,11 +1029,11 @@ static term div_maybe_bigint(Context *ctx, uint32_t fail_label, uint32_t live, t
const intn_digit_t *bn1;
size_t bn1_len;
intn_integer_sign_t bn1_sign;
term_to_bigint(arg1, tmp_buf1, &bn1, &bn1_len, &bn1_sign);
conv_term_to_bigint(arg1, tmp_buf1, &bn1, &bn1_len, &bn1_sign);
const intn_digit_t *bn2;
size_t bn2_len;
intn_integer_sign_t bn2_sign;
term_to_bigint(arg2, tmp_buf2, &bn2, &bn2_len, &bn2_sign);
conv_term_to_bigint(arg2, tmp_buf2, &bn2, &bn2_len, &bn2_sign);

int cmp_result = intn_cmp(bn1, bn1_len, bn2, bn2_len);
if (cmp_result < 0) {
Expand Down Expand Up @@ -1146,10 +1137,10 @@ term bif_erlang_div_2(Context *ctx, uint32_t fail_label, int live, term arg1, te
// that just copies the given term but changes the sign
static term neg_bigint(Context *ctx, uint32_t fail_label, uint32_t live, term arg1)
{
// update when updating term_to_bigint
intn_digit_t *m = term_intn_data(arg1);
size_t m_len = term_intn_size(arg1) * (sizeof(term) / sizeof(intn_digit_t));
intn_integer_sign_t m_sign = (intn_integer_sign_t) term_boxed_integer_sign(arg1);
const intn_digit_t *m;
size_t m_len;
intn_integer_sign_t m_sign;
term_to_bigint(arg1, &m, &m_len, &m_sign);

intn_digit_t tmp_copy[INTN_MAX_RES_LEN];
memcpy(tmp_copy, m, m_len * sizeof(intn_digit_t));
Expand Down Expand Up @@ -1242,9 +1233,10 @@ term bif_erlang_neg_1(Context *ctx, uint32_t fail_label, int live, term arg1)
// that just copies the given term but changes the sign
static term abs_bigint(Context *ctx, uint32_t fail_label, uint32_t live, term arg1)
{
// update when updating term_to_bigint
intn_digit_t *m = term_intn_data(arg1);
size_t m_len = term_intn_size(arg1) * (sizeof(term) / sizeof(intn_digit_t));
const intn_digit_t *m;
size_t m_len;
intn_integer_sign_t discarded_sign;
term_to_bigint(arg1, &m, &m_len, &discarded_sign);

intn_digit_t tmp_copy[INTN_MAX_RES_LEN];
memcpy(tmp_copy, m, m_len * sizeof(intn_digit_t));
Expand Down Expand Up @@ -1359,11 +1351,11 @@ static term rem_maybe_bigint(Context *ctx, uint32_t fail_label, uint32_t live, t
const intn_digit_t *bn1;
size_t bn1_len;
intn_integer_sign_t bn1_sign;
term_to_bigint(arg1, tmp_buf1, &bn1, &bn1_len, &bn1_sign);
conv_term_to_bigint(arg1, tmp_buf1, &bn1, &bn1_len, &bn1_sign);
const intn_digit_t *bn2;
size_t bn2_len;
intn_integer_sign_t bn2_sign;
term_to_bigint(arg2, tmp_buf2, &bn2, &bn2_len, &bn2_sign);
conv_term_to_bigint(arg2, tmp_buf2, &bn2, &bn2_len, &bn2_sign);

int cmp_result = intn_cmp(bn1, bn1_len, bn2, bn2_len);
if (cmp_result < 0) {
Expand Down Expand Up @@ -1622,11 +1614,11 @@ static inline term bitwise_helper(
const intn_digit_t *m;
size_t m_len;
intn_integer_sign_t m_sign;
term_to_bigint(arg1, tmp_buf1, &m, &m_len, &m_sign);
conv_term_to_bigint(arg1, tmp_buf1, &m, &m_len, &m_sign);
const intn_digit_t *n;
size_t n_len;
intn_integer_sign_t n_sign;
term_to_bigint(arg2, tmp_buf2, &n, &n_len, &n_sign);
conv_term_to_bigint(arg2, tmp_buf2, &n, &n_len, &n_sign);

intn_digit_t bigres[INTN_MAX_RES_LEN];
intn_integer_sign_t bigres_sign;
Expand Down Expand Up @@ -1702,7 +1694,7 @@ term bif_erlang_bsl_2(Context *ctx, uint32_t fail_label, int live, term arg1, te
const intn_digit_t *m;
size_t m_len;
intn_integer_sign_t m_sign;
term_to_bigint(arg1, tmp_buf1, &m, &m_len, &m_sign);
conv_term_to_bigint(arg1, tmp_buf1, &m, &m_len, &m_sign);

intn_digit_t bigres[INTN_MAX_RES_LEN];
size_t bigres_len = intn_bsl(m, m_len, b, bigres);
Expand Down Expand Up @@ -1762,7 +1754,7 @@ term bif_erlang_bsr_2(Context *ctx, uint32_t fail_label, int live, term arg1, te
const intn_digit_t *m;
size_t m_len;
intn_integer_sign_t m_sign;
term_to_bigint(arg1, tmp_buf1, &m, &m_len, &m_sign);
conv_term_to_bigint(arg1, tmp_buf1, &m, &m_len, &m_sign);

intn_digit_t bigres[INTN_MAX_RES_LEN];
size_t bigres_len = intn_bsr(m, m_len, m_sign, b, bigres);
Expand Down Expand Up @@ -1823,7 +1815,7 @@ static term bnot_boxed_helper(Context *ctx, uint32_t fail_label, uint32_t live,
const intn_digit_t *m;
size_t m_len;
intn_integer_sign_t m_sign;
term_to_bigint(arg1, tmp_buf1, &m, &m_len, &m_sign);
conv_term_to_bigint(arg1, tmp_buf1, &m, &m_len, &m_sign);

intn_digit_t bigres[INTN_MAX_RES_LEN];
intn_integer_sign_t bigres_sign;
Expand Down
21 changes: 9 additions & 12 deletions src/libAtomVM/externalterm.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,14 +234,12 @@ static int serialize_term(uint8_t *buf, term t, GlobalContext *glb)
return SMALL_BIG_EXT_BASE_SIZE + num_bytes;
}
} else {
size_t intn_size = term_intn_size(t);
size_t digits_per_term = sizeof(term) / sizeof(intn_digit_t);
size_t bigint_len = intn_size * digits_per_term;
const intn_digit_t *bigint = (const intn_digit_t *) term_intn_data(t);
const intn_digit_t *bigint;
size_t bigint_len;
intn_integer_sign_t sign;
term_to_bigint(t, &bigint, &bigint_len, &sign);
size_t num_bytes = intn_required_unsigned_integer_bytes(bigint, bigint_len);
if (buf != NULL) {
intn_integer_sign_t sign = (intn_integer_sign_t) term_boxed_integer_sign(t);

buf[0] = SMALL_BIG_EXT;
buf[1] = num_bytes;
buf[2] = sign == IntNNegativeInteger ? 0x01 : 0x00;
Expand Down Expand Up @@ -594,13 +592,12 @@ static term parse_external_terms(const uint8_t *external_term_buf, size_t *eterm

size_t intn_data_size;
size_t rounded_res_len;
term_intn_to_term_size(count, &intn_data_size, &rounded_res_len);
term_bigint_size_requirements(count, &intn_data_size, &rounded_res_len);

intn_integer_sign_t sign = is_negative ? IntNNegativeInteger : IntNPositiveInteger;
term bigint_term
= term_create_uninitialized_intn(intn_data_size, (term_integer_sign_t) sign, heap);
intn_digit_t *dest_buf = (void *) term_intn_data(bigint_term);
intn_copy(bigint, count, dest_buf, rounded_res_len);
= term_create_uninitialized_bigint(intn_data_size, (term_integer_sign_t) sign, heap);
term_initialize_bigint(bigint_term, bigint, count, rounded_res_len);

return bigint_term;
}
Expand Down Expand Up @@ -1014,8 +1011,8 @@ static int calculate_heap_usage(const uint8_t *external_term_buf, size_t remaini
size_t required_digits = intn_required_digits_for_unsigned_integer(num_bytes);
size_t data_size;
size_t unused_rounded_len;
term_intn_to_term_size(required_digits, &data_size, &unused_rounded_len);
return BOXED_INTN_SIZE(data_size);
term_bigint_size_requirements(required_digits, &data_size, &unused_rounded_len);
return BOXED_BIGINT_HEAP_SIZE(data_size);
}

case ATOM_UTF8_EXT:
Expand Down
10 changes: 6 additions & 4 deletions src/libAtomVM/jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -627,17 +627,19 @@ static term jit_alloc_big_integer_fragment(

size_t intn_data_size;
size_t rounded_res_len;
term_intn_to_term_size(digits_len, &intn_data_size, &rounded_res_len);
term_bigint_size_requirements(digits_len, &intn_data_size, &rounded_res_len);

if (UNLIKELY(memory_init_heap(&heap, BOXED_INTN_SIZE(intn_data_size)) != MEMORY_GC_OK)) {
if (UNLIKELY(memory_init_heap(&heap, BOXED_BIGINT_HEAP_SIZE(intn_data_size)) != MEMORY_GC_OK)) {
ctx->x[0] = ERROR_ATOM;
ctx->x[1] = OUT_OF_MEMORY_ATOM;
return term_invalid_term();
}

term bigint_term
= term_create_uninitialized_intn(intn_data_size, (term_integer_sign_t) sign, &heap);
void *digits_mem = term_intn_data(bigint_term);
= term_create_uninitialized_bigint(intn_data_size, (term_integer_sign_t) sign, &heap);
// Assumption: here we assume that bigints have standard boxed term layout
// This code might need to be updated when changing bigint memory layout
void *digits_mem = (void *) (term_to_const_term_ptr(bigint_term) + 1);
// TODO: optimize: just initialize space that will not be used
memset(digits_mem, 0, intn_data_size * sizeof(term));

Expand Down
20 changes: 9 additions & 11 deletions src/libAtomVM/nifs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2057,16 +2057,15 @@ static term make_bigint(Context *ctx, const intn_digit_t bigres[], size_t bigres
{
size_t intn_data_size;
size_t rounded_res_len;
term_intn_to_term_size(bigres_len, &intn_data_size, &rounded_res_len);
term_bigint_size_requirements(bigres_len, &intn_data_size, &rounded_res_len);

if (UNLIKELY(memory_ensure_free(ctx, BOXED_INTN_SIZE(intn_data_size)) != MEMORY_GC_OK)) {
if (UNLIKELY(memory_ensure_free(ctx, BOXED_BIGINT_HEAP_SIZE(intn_data_size)) != MEMORY_GC_OK)) {
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
}

term bigres_term
= term_create_uninitialized_intn(intn_data_size, (term_integer_sign_t) sign, &ctx->heap);
intn_digit_t *dest_buf = (void *) term_intn_data(bigres_term);
intn_copy(bigres, bigres_len, dest_buf, rounded_res_len);
= term_create_uninitialized_bigint(intn_data_size, (term_integer_sign_t) sign, &ctx->heap);
term_initialize_bigint(bigres_term, bigres, bigres_len, rounded_res_len);

return bigres_term;
}
Expand Down Expand Up @@ -2396,12 +2395,11 @@ static term integer_to_buf(Context *ctx, int argc, term argv[], char *tmp_buf, s
}
#endif
default: {
size_t boxed_size = term_intn_size(value);
size_t digits_per_term = sizeof(term) / sizeof(intn_digit_t);
const intn_digit_t *intn_buf = (const intn_digit_t *) term_intn_data(value);
intn_integer_sign_t sign = (intn_integer_sign_t) term_boxed_integer_sign(value);
*int_buf
= intn_to_string(intn_buf, boxed_size * digits_per_term, sign, base, int_len);
const intn_digit_t *intn_buf;
size_t intn_buf_len;
intn_integer_sign_t sign;
term_to_bigint(value, &intn_buf, &intn_buf_len, &sign);
*int_buf = intn_to_string(intn_buf, intn_buf_len, sign, base, int_len);
*needs_cleanup = true;
}
}
Expand Down
9 changes: 4 additions & 5 deletions src/libAtomVM/opcodesswitch.h
Original file line number Diff line number Diff line change
Expand Up @@ -1840,21 +1840,20 @@ static bool maybe_call_native(Context *ctx, atom_index_t module_name, atom_index

size_t intn_data_size;
size_t rounded_res_len;
term_intn_to_term_size(count, &intn_data_size, &rounded_res_len);
term_bigint_size_requirements(count, &intn_data_size, &rounded_res_len);

Heap heap;
if (UNLIKELY(
memory_init_heap(&heap, BOXED_INTN_SIZE(intn_data_size)) != MEMORY_GC_OK)) {
memory_init_heap(&heap, BOXED_BIGINT_HEAP_SIZE(intn_data_size)) != MEMORY_GC_OK)) {
ctx->x[0] = ERROR_ATOM;
ctx->x[1] = OUT_OF_MEMORY_ATOM;
*out_term = term_invalid_term();
goto return_size;
}

term bigint_term
= term_create_uninitialized_intn(intn_data_size, (term_integer_sign_t) sign, &heap);
intn_digit_t *dest_buf = (void *) term_intn_data(bigint_term);
intn_copy(bigint, count, dest_buf, rounded_res_len);
= term_create_uninitialized_bigint(intn_data_size, (term_integer_sign_t) sign, &heap);
term_initialize_bigint(bigint_term, bigint, count, rounded_res_len);

memory_heap_append_heap(&ctx->heap, &heap);

Expand Down
21 changes: 10 additions & 11 deletions src/libAtomVM/term.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,13 +420,12 @@ int term_funprint(PrinterFun *fun, term t, const GlobalContext *global)
return fun->print(fun, AVM_INT64_FMT, term_unbox_int64(t));
#endif
default: {
size_t digits_per_term = sizeof(term) / sizeof(intn_digit_t);
size_t boxed_size = term_intn_size(t);
const intn_digit_t *intn_data = (const intn_digit_t *) term_intn_data(t);
intn_integer_sign_t sign = (intn_integer_sign_t) term_boxed_integer_sign(t);
const intn_digit_t *intn_data;
size_t intn_data_len;
intn_integer_sign_t sign;
term_to_bigint(t, &intn_data, &intn_data_len, &sign);
size_t unused_s_len;
char *s = intn_to_string(
intn_data, boxed_size * digits_per_term, sign, 10, &unused_s_len);
char *s = intn_to_string(intn_data, intn_data_len, sign, 10, &unused_s_len);
if (IS_NULL_PTR(s)) {
return -1;
}
Expand Down Expand Up @@ -1087,12 +1086,12 @@ avm_float_t term_conv_to_float(term t)
return term_unbox_int64(t);
#endif
default: {
const intn_digit_t *num = (intn_digit_t *) term_intn_data(t);
size_t digits_per_term = (sizeof(term) / sizeof(intn_digit_t));
size_t len = boxed_size * digits_per_term;
term_integer_sign_t t_sign = term_boxed_integer_sign(t);
const intn_digit_t *num;
size_t num_len;
intn_integer_sign_t num_sign;
term_to_bigint(t, &num, &num_len, &num_sign);

return intn_to_double(num, len, (intn_integer_sign_t) t_sign);
return intn_to_double(num, num_len, num_sign);
}
}
} else {
Expand Down
Loading
Loading