Skip to content
Open
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
9 changes: 9 additions & 0 deletions erts/emulator/beam/emu/arith_instrs.tab
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ OUTLINED_ARITH_1(Fail, Name, BIF, Op1,Dst) {
Eterm* orig_stop = E;
#endif
DEBUG_SWAPOUT;
c_p->fcalls = FCALLS;
result = erts_$Name (c_p, $Op1);
FCALLS = c_p->fcalls;
DEBUG_SWAPIN;
ASSERT(orig_htop == HTOP && orig_stop == E);
ERTS_HOLE_CHECK(c_p);
Expand All @@ -46,7 +48,9 @@ OUTLINED_ARITH_2(Fail, Name, BIF, Op1, Op2, Dst) {
Eterm* orig_stop = E;
#endif
DEBUG_SWAPOUT;
c_p->fcalls = FCALLS;
result = erts_$Name (c_p, $Op1, $Op2);
FCALLS = c_p->fcalls;
DEBUG_SWAPIN;
ASSERT(orig_htop == HTOP && orig_stop == E);
ERTS_HOLE_CHECK(c_p);
Expand Down Expand Up @@ -487,6 +491,9 @@ shift.execute(Fail, Dst) {
}
ERTS_HOLE_CHECK(c_p);
$Dst = Op1;
c_p->fcalls = FCALLS;
BUMP_REDS(c_p, big_need_size / ERTS_ARITH_WORDS_PER_REDUCTION + 1);
FCALLS = c_p->fcalls;
$NEXT0();
}
}
Expand Down Expand Up @@ -514,7 +521,9 @@ i_int_bnot(Fail, Src, Dst) {
if (ERTS_LIKELY(is_small(bnot_val))) {
result = make_small(~signed_val(bnot_val));
} else {
c_p->fcalls = FCALLS;
result = erts_bnot(c_p, bnot_val);
FCALLS = c_p->fcalls;
ERTS_HOLE_CHECK(c_p);
if (ERTS_UNLIKELY(is_non_value(result))) {
$BIF_ERROR_ARITY_1($Fail, BIF_bnot_1, bnot_val);
Expand Down
61 changes: 51 additions & 10 deletions erts/emulator/beam/erl_arith.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,13 @@ erts_shift(Process* p, Eterm arg1, Eterm arg2, int right)
maybe_shrink(p, bigp, arg1, need);
if (is_nil(arg1)) {
/*
* This result must have been only slight larger
* This result must have been only slightly larger
* than allowed since it wasn't caught by the
* previous test.
*/
BIF_ERROR(p, SYSTEM_LIMIT);
}
BUMP_REDS(p, need / ERTS_ARITH_WORDS_PER_REDUCTION + 1);
BIF_RET(arg1);
} else if (is_big(arg1)) {
if (i == 0) {
Expand Down Expand Up @@ -298,6 +299,7 @@ BIF_RETTYPE bnot_1(BIF_ALIST_1)
if (is_nil(ret)) {
BIF_ERROR(BIF_P, SYSTEM_LIMIT);
}
BUMP_REDS(BIF_P, need / ERTS_ARITH_WORDS_PER_REDUCTION + 1);
} else {
BIF_ERROR(BIF_P, BADARITH);
}
Expand Down Expand Up @@ -399,6 +401,7 @@ erts_mixed_plus(Process* p, Eterm arg1, Eterm arg2)
p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}
BUMP_REDS(p, need_heap / ERTS_ARITH_WORDS_PER_REDUCTION + 1);
return res;
case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):
if (big_to_double(arg1, &f1.fd) < 0) {
Expand Down Expand Up @@ -502,6 +505,7 @@ erts_unary_minus(Process* p, Eterm arg)
res = big_minus(zero, arg, hp);
maybe_shrink(p, hp, res, need_heap);
ASSERT(is_not_nil(res));
BUMP_REDS(p, need_heap / ERTS_ARITH_WORDS_PER_REDUCTION + 1);
return res;
}
case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):
Expand Down Expand Up @@ -599,6 +603,7 @@ erts_mixed_minus(Process* p, Eterm arg1, Eterm arg2)
p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}
BUMP_REDS(p, sz);
return res;
default:
goto badarith;
Expand Down Expand Up @@ -804,10 +809,15 @@ erts_mixed_times(Process* p, Eterm arg1, Eterm arg2)

maybe_shrink(p, hp, res, need_heap);
if (is_nil(res)) {
p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}
return res;
p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}

/* Conservative estimate of effort, assuming
* schoolbook multiplication. */
BUMP_REDS(p, big_size(arg1) * big_size(arg2) /
ERTS_ARITH_WORDS_PER_REDUCTION + 1);
return res;
case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):
if (big_to_double(arg1, &f1.fd) < 0) {
goto badarith;
Expand Down Expand Up @@ -938,6 +948,10 @@ erts_mul_add(Process* p, Eterm arg1, Eterm arg2, Eterm arg3, Eterm* pp)
p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}

/* Conservative estimate of effort,
* assuming schoolbook multiplication. */
BUMP_REDS(p, sz1 * sz2 / ERTS_ARITH_WORDS_PER_REDUCTION + 1);
return res;
}
}
Expand Down Expand Up @@ -1160,7 +1174,7 @@ int erts_int_div_rem(Process* p, Eterm arg1, Eterm arg2, Eterm *q, Eterm *r)
SMALL_ONE : SMALL_MINUS_ONE;
remainder = SMALL_ZERO;
} else {
int lhs_size, rhs_size;
unsigned lhs_size, rhs_size;
Uint q_need, r_need;
Eterm *q_hp, *r_hp;

Expand All @@ -1184,6 +1198,12 @@ int erts_int_div_rem(Process* p, Eterm arg1, Eterm arg2, Eterm *q, Eterm *r)

ASSERT(q_need + r_need >= size_object(quotient) + size_object(remainder));

/* Conservative estimate of effort, assuming shoolbook long
* division. */
ASSERT(lhs_size >= rhs_size);
BUMP_REDS(p, (lhs_size - rhs_size + 1) * rhs_size /
ERTS_ARITH_WORDS_PER_REDUCTION + 1);

div_rem_shrink(p, q_hp, quotient, r_hp, remainder);
}

Expand Down Expand Up @@ -1227,18 +1247,25 @@ erts_int_div(Process* p, Eterm arg1, Eterm arg2)
SMALL_ONE : SMALL_MINUS_ONE;
} else {
Eterm* hp;
int i = big_size(arg1);
unsigned lhs_size = big_size(arg1);
unsigned rhs_size = big_size(arg2);
Uint need;

ires = big_size(arg2);
need = BIG_NEED_SIZE(i-ires+1) + BIG_NEED_SIZE(i);
need = BIG_NEED_SIZE(lhs_size-rhs_size+1) +
BIG_NEED_SIZE(lhs_size);
hp = HeapFragOnlyAlloc(p, need);
arg1 = big_div(arg1, arg2, hp);
maybe_shrink(p, hp, arg1, need);
if (is_nil(arg1)) {
p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}

/* Conservative estimate of effort, assuming shoolbook
* long division. */
ASSERT(lhs_size >= rhs_size);
BUMP_REDS(p, (lhs_size - rhs_size + 1) * rhs_size /
ERTS_ARITH_WORDS_PER_REDUCTION + 1);
}
return arg1;
default:
Expand Down Expand Up @@ -1282,7 +1309,9 @@ erts_int_rem(Process* p, Eterm arg1, Eterm arg2)
if (ires == 0) {
arg1 = SMALL_ZERO;
} else if (ires > 0) {
Uint need = BIG_NEED_SIZE(big_size(arg1));
unsigned lhs_size = big_size(arg1);
unsigned rhs_size;
Uint need = BIG_NEED_SIZE(lhs_size);
Eterm* hp = HeapFragOnlyAlloc(p, need);

arg1 = big_rem(arg1, arg2, hp);
Expand All @@ -1291,6 +1320,14 @@ erts_int_rem(Process* p, Eterm arg1, Eterm arg2)
p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}

/* Conservative estimate of effort, assuming shoolbook
* long division. */
rhs_size = big_size(arg2);
ASSERT(lhs_size >= rhs_size);
BUMP_REDS(p, (lhs_size - rhs_size + 1) * rhs_size /
ERTS_ARITH_WORDS_PER_REDUCTION + 1);

}
return arg1;
default:
Expand Down Expand Up @@ -1323,6 +1360,7 @@ Eterm erts_band(Process* p, Eterm arg1, Eterm arg2)
arg1 = big_band(arg1, arg2, hp);
ASSERT(is_not_nil(arg1));
maybe_shrink(p, hp, arg1, need);
BUMP_REDS(p, need / ERTS_ARITH_WORDS_PER_REDUCTION + 1);
return arg1;
}

Expand Down Expand Up @@ -1350,6 +1388,7 @@ Eterm erts_bor(Process* p, Eterm arg1, Eterm arg2)
arg1 = big_bor(arg1, arg2, hp);
ASSERT(is_not_nil(arg1));
maybe_shrink(p, hp, arg1, need);
BUMP_REDS(p, need / ERTS_ARITH_WORDS_PER_REDUCTION + 1);
return arg1;
}

Expand Down Expand Up @@ -1377,6 +1416,7 @@ Eterm erts_bxor(Process* p, Eterm arg1, Eterm arg2)
arg1 = big_bxor(arg1, arg2, hp);
ASSERT(is_not_nil(arg1));
maybe_shrink(p, hp, arg1, need);
BUMP_REDS(p, need / ERTS_ARITH_WORDS_PER_REDUCTION + 1);
return arg1;
}

Expand All @@ -1394,6 +1434,7 @@ Eterm erts_bnot(Process* p, Eterm arg)
p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}
BUMP_REDS(p, need / ERTS_ARITH_WORDS_PER_REDUCTION + 1);
} else {
p->freason = BADARITH;
return THE_NON_VALUE;
Expand Down
5 changes: 5 additions & 0 deletions erts/emulator/beam/global.h
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,11 @@ void erts_print_base64(fmtfn_t to, void *to_arg, const byte* src, Uint size);
int erts_set_signal(Eterm signal, Eterm type);

/* erl_arith.c */

/* The number of bignum words that we assume can be processed in one
* reduction. */
#define ERTS_ARITH_WORDS_PER_REDUCTION 16

double erts_get_positive_zero_float(void);

/* config.c */
Expand Down
Loading
Loading