📄 erl_arith.c
字号:
break; case BIG_BIG: break; default: p->freason = BADARITH; return THE_NON_VALUE; } need = BIG_NEED_SIZE(MAX(big_size(arg1), big_size(arg2)) + 1); hp = ArithAlloc(p, need); arg1 = big_band(arg1, arg2, hp); ASSERT(is_not_nil(arg1)); maybe_shrink(p, hp, arg1, need); ArithCheck(p); return arg1;}Eterm erts_bor(Process* p, Eterm arg1, Eterm arg2){ Eterm tmp_big1[2]; Eterm tmp_big2[2]; Eterm* hp; int need; switch (NUMBER_CODE(arg1, arg2)) { case SMALL_BIG: arg1 = small_to_big(signed_val(arg1), tmp_big1); break; case BIG_SMALL: arg2 = small_to_big(signed_val(arg2), tmp_big2); break; case BIG_BIG: break; default: p->freason = BADARITH; return THE_NON_VALUE; } need = BIG_NEED_SIZE(MAX(big_size(arg1), big_size(arg2)) + 1); hp = ArithAlloc(p, need); arg1 = big_bor(arg1, arg2, hp); ASSERT(is_not_nil(arg1)); maybe_shrink(p, hp, arg1, need); ArithCheck(p); return arg1;}Eterm erts_bxor(Process* p, Eterm arg1, Eterm arg2){ Eterm tmp_big1[2]; Eterm tmp_big2[2]; Eterm* hp; int need; switch (NUMBER_CODE(arg1, arg2)) { case SMALL_BIG: arg1 = small_to_big(signed_val(arg1), tmp_big1); break; case BIG_SMALL: arg2 = small_to_big(signed_val(arg2), tmp_big2); break; case BIG_BIG: break; default: p->freason = BADARITH; return THE_NON_VALUE; } need = BIG_NEED_SIZE(MAX(big_size(arg1), big_size(arg2)) + 1); hp = ArithAlloc(p, need); arg1 = big_bxor(arg1, arg2, hp); ASSERT(is_not_nil(arg1)); maybe_shrink(p, hp, arg1, need); ArithCheck(p); return arg1;}Eterm erts_bnot(Process* p, Eterm arg){ Eterm ret; if (is_big(arg)) { Uint need = BIG_NEED_SIZE(big_size(arg)+1); Eterm* bigp = ArithAlloc(p, need); ret = big_bnot(arg, bigp); maybe_shrink(p, bigp, ret, need); if (is_nil(ret)) { p->freason = SYSTEM_LIMIT; return NIL; } ArithCheck(p); } else { p->freason = BADARITH; return NIL; } return ret;} #if defined(HEAP_FRAG_ELIM_TEST)#define ERTS_ARITH_FORCE_GC 0#define ERTS_NEED_GC(p, need) \ (ERTS_ARITH_FORCE_GC || (HEAP_LIMIT((p)) - HEAP_TOP((p))) <= (need))static ERTS_INLINE voidtrim_heap(Process* p, Eterm* hp, Eterm res){ if (is_immed(res)) { ASSERT(p->heap <= hp && hp <= p->htop); p->htop = hp; } else { Eterm* new_htop; ASSERT(is_big(res)); new_htop = hp + bignum_header_arity(*hp) + 1; ASSERT(p->heap <= new_htop && new_htop <= p->htop); p->htop = new_htop; } ASSERT(p->heap <= p->htop && p->htop <= p->stop);}/* * The following are not allowed to be used here */#define erts_arith_shrink horrible error#define maybe_shrink horrible error#undef ArithAlloc#undef ArithCheck#define ArithAlloc horrible error#define ArithCheck horrible errorEtermerts_gc_mixed_plus(Process* p, Eterm* reg, Uint live){ Eterm arg1; Eterm arg2; Eterm tmp_big1[2]; Eterm tmp_big2[2]; Eterm res; Eterm hdr; FloatDef f1, f2; dsize_t sz1, sz2, sz; int need_heap; Eterm* hp; Sint ires; arg1 = reg[live]; arg2 = reg[live+1]; ERTS_FP_CHECK_INIT(p); switch (arg1 & _TAG_PRIMARY_MASK) { case TAG_PRIMARY_IMMED1: switch ((arg1 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): switch (arg2 & _TAG_PRIMARY_MASK) { case TAG_PRIMARY_IMMED1: switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): ires = signed_val(arg1) + signed_val(arg2); ASSERT(MY_IS_SSMALL(ires) == IS_SSMALL(ires)); if (MY_IS_SSMALL(ires)) { return make_small(ires); } else { if (ERTS_NEED_GC(p, 2)) { erts_garbage_collect(p, 2, reg, live); } hp = p->htop; p->htop += 2; res = small_to_big(ires, hp); return res; } default: badarith: p->freason = BADARITH; return THE_NON_VALUE; } case TAG_PRIMARY_BOXED: hdr = *boxed_val(arg2); switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE): case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE): if (arg1 == SMALL_ZERO) { return arg2; } arg1 = small_to_big(signed_val(arg1), tmp_big1); goto do_big; case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE): f1.fd = signed_val(arg1); GET_DOUBLE(arg2, f2); goto do_float; default: goto badarith; } } default: goto badarith; } case TAG_PRIMARY_BOXED: hdr = *boxed_val(arg1); switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE): case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE): switch (arg2 & _TAG_PRIMARY_MASK) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): if (arg2 == SMALL_ZERO) { return arg1; } arg2 = small_to_big(signed_val(arg2), tmp_big2); goto do_big; default: goto badarith; } case TAG_PRIMARY_BOXED: hdr = *boxed_val(arg2); switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE): case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE): do_big: sz1 = big_size(arg1); sz2 = big_size(arg2); sz = MAX(sz1, sz2)+1; need_heap = BIG_NEED_SIZE(sz); if (ERTS_NEED_GC(p, need_heap)) { erts_garbage_collect(p, need_heap, reg, live+2); if (arg1 != make_big(tmp_big1)) { arg1 = reg[live]; } if (arg2 != make_big(tmp_big2)) { arg2 = reg[live+1]; } } hp = p->htop; p->htop += need_heap; res = big_plus(arg1, arg2, hp); trim_heap(p, hp, res); if (is_nil(res)) { p->freason = SYSTEM_LIMIT; return THE_NON_VALUE; } return res; case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE): if (big_to_double(arg1, &f1.fd) < 0) { goto badarith; } GET_DOUBLE(arg2, f2); goto do_float; default: goto badarith; } } case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE): switch (arg2 & _TAG_PRIMARY_MASK) { case TAG_PRIMARY_IMMED1: switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): GET_DOUBLE(arg1, f1); f2.fd = signed_val(arg2); goto do_float; default: goto badarith; } case TAG_PRIMARY_BOXED: hdr = *boxed_val(arg2); switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE): case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE): GET_DOUBLE(arg1, f1); if (big_to_double(arg2, &f2.fd) < 0) { goto badarith; } goto do_float; case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE): GET_DOUBLE(arg1, f1); GET_DOUBLE(arg2, f2); do_float: f1.fd = f1.fd + f2.fd; ERTS_FP_ERROR(p, f1.fd, goto badarith); if (ERTS_NEED_GC(p, FLOAT_SIZE_OBJECT)) { erts_garbage_collect(p, FLOAT_SIZE_OBJECT, reg, live); } hp = p->htop; p->htop += FLOAT_SIZE_OBJECT; res = make_float(hp); PUT_DOUBLE(f1, hp); return res; default: goto badarith; } default: goto badarith; } } default: goto badarith; }}Etermerts_gc_mixed_minus(Process* p, Eterm* reg, Uint live){ Eterm arg1; Eterm arg2; Eterm tmp_big1[2]; Eterm tmp_big2[2]; Eterm hdr; Eterm res; FloatDef f1, f2; dsize_t sz1, sz2, sz; int need_heap; Eterm* hp; Sint ires; arg1 = reg[live]; arg2 = reg[live+1]; ERTS_FP_CHECK_INIT(p); switch (arg1 & _TAG_PRIMARY_MASK) { case TAG_PRIMARY_IMMED1: switch ((arg1 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): switch (arg2 & _TAG_PRIMARY_MASK) { case TAG_PRIMARY_IMMED1: switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): ires = signed_val(arg1) - signed_val(arg2); ASSERT(MY_IS_SSMALL(ires) == IS_SSMALL(ires)); if (MY_IS_SSMALL(ires)) { return make_small(ires); } else { if (ERTS_NEED_GC(p, 2)) { erts_garbage_collect(p, 2, reg, live); } hp = p->htop; p->htop += 2; res = small_to_big(ires, hp); return res; } default: badarith: p->freason = BADARITH; return THE_NON_VALUE; } case TAG_PRIMARY_BOXED: hdr = *boxed_val(arg2); switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE): case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE): arg1 = small_to_big(signed_val(arg1), tmp_big1); goto do_big; case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE): f1.fd = signed_val(arg1); GET_DOUBLE(arg2, f2); goto do_float; default: goto badarith; } } default: goto badarith; } case TAG_PRIMARY_BOXED: hdr = *boxed_val(arg1); switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE): case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE): switch (arg2 & _TAG_PRIMARY_MASK) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): if (arg2 == SMALL_ZERO) { return arg1; } arg2 = small_to_big(signed_val(arg2), tmp_big2); do_big: sz1 = big_size(arg1); sz2 = big_size(arg2); sz = MAX(sz1, sz2)+1; need_heap = BIG_NEED_SIZE(sz); if (ERTS_NEED_GC(p, need_heap)) { erts_garbage_collect(p, need_heap, reg, live+2); if (arg1 != make_big(tmp_big1)) { arg1 = reg[live]; } if (arg2 != make_big(tmp_big2)) { arg2 = reg[live+1]; } } hp = p->htop; p->htop += need_heap; res = big_minus(arg1, arg2, hp); trim_heap(p, hp, res); if (is_nil(res)) { p->freason = SYSTEM_LIMIT; return THE_NON_VALUE; } return res; default: goto badarith; } case TAG_PRIMARY_BOXED: hdr = *boxed_val(arg2); switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE): case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE): goto do_big; case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE): if (big_to_double(arg1, &f1.fd) < 0) { goto badarith; } GET_DOUBLE(arg2, f2); goto do_float; default: goto badarith; } } case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE): switch (arg2 & _TAG_PRIMARY_MASK) { case TAG_PRIMARY_IMMED1: switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): GET_DOUBLE(arg1, f1); f2.fd = signed_val(arg2); goto do_float; default: goto badarith; } case TAG_PRIMARY_BOXED: hdr = *boxed_val(arg2); switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE): case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE): GET_DOUBLE(arg1, f1); if (big_to_double(arg2, &f2.fd) < 0) { goto badarith; } goto do_float; case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE): GET_DOUBLE(arg1, f1); GET_DOUBLE(arg2, f2); do_float: f1.fd = f1.fd - f2.fd; ERTS_FP_ERROR(p, f1.fd, goto badarith); if (ERTS_NEED_GC(p, FLOAT_SIZE_OBJECT)) { erts_garbage_collect(p, FLOAT_SIZE_OBJECT, reg, live); } hp = p->htop; p->htop += FLOAT_SIZE_OBJECT; res = make_float(hp); PUT_DOUBLE(f1, hp); return res; default: goto badarith; } default: goto badarith; } } default: goto badarith; }}Etermerts_gc_mixed_times(Process* p, Eterm* reg, Uint live){ Eterm arg1; Eterm arg2; Eterm tmp_big1[2]; Eterm tmp_big2[2]; Eterm hdr; Eterm res; FloatDef f1, f2; dsize_t sz1, sz2, sz; int need_heap; Eterm* hp; arg1 = reg[live]; arg2 = reg[live+1]; ERTS_FP_CHECK_INIT(p); switch (arg1 & _TAG_PRIMARY_MASK) { case TAG_PRIMARY_IMMED1: switch ((arg1 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): switch (arg2 & _TAG_PRIMARY_MASK) { case TAG_PRIMARY_IMMED1: switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): if ((arg1 == SMALL_ZERO) || (arg2 == SMALL_ZERO)) { return(SMALL_ZERO); } else if (arg1 == SMALL_ONE) { return(arg2); } else if (arg2 == SMALL_ONE) { return(arg1); } else { Eterm big_res[3]; /* * The following code is optimized for the case that * result is small (which should be the most common case * in practice). */ arg1 = small_to_big(signed_val(arg1), tmp_big1); arg2 = small_to_big(signed_val(arg2), tmp_big2); res = big_times(arg1, arg2, big_res); if (is_small(res)) { return res;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -