* insns.def (opt_mult): Use int128_t for overflow detection.

* bignum.c (rb_uint128t2big): added for opt_mult.

* bignum.c (rb_uint128t2big): added for rb_uint128t2big..

* configure.in: define int128_t, uint128_t and related MACROs.
  Initially introduced by r41379 but reverted by r50749.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53741 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
naruse 2016-02-05 04:31:27 +00:00
Родитель b658249cef
Коммит 1f57a334da
4 изменённых файлов: 72 добавлений и 8 удалений

Просмотреть файл

@ -1,3 +1,14 @@
Fri Feb 5 12:22:20 2016 NARUSE, Yui <naruse@ruby-lang.org>
* insns.def (opt_mult): Use int128_t for overflow detection.
* bignum.c (rb_uint128t2big): added for opt_mult.
* bignum.c (rb_uint128t2big): added for rb_uint128t2big..
* configure.in: define int128_t, uint128_t and related MACROs.
Initially introduced by r41379 but reverted by r50749.
Thu Feb 4 21:05:17 2016 Martin Duerst <duerst@it.aoyama.ac.jp>
* enc/unicode.c: Activated :ascii flag for ASCII-only case conversion

Просмотреть файл

@ -4367,6 +4367,46 @@ rb_ll2inum(LONG_LONG n)
#endif /* HAVE_LONG_LONG */
#ifdef HAVE_INT128_T
static VALUE
rb_uint128t2big(uint128_t n)
{
long i;
VALUE big = bignew(bdigit_roomof(SIZEOF_INT128_T), 1);
BDIGIT *digits = BDIGITS(big);
for (i = 0; i < bdigit_roomof(SIZEOF_INT128_T); i++) {
digits[i] = BIGLO(RSHIFT(n ,BITSPERDIG*i));
}
i = bdigit_roomof(SIZEOF_INT128_T);
while (i-- && !digits[i]) ;
BIGNUM_SET_LEN(big, i+1);
return big;
}
VALUE
rb_int128t2big(int128_t n)
{
int neg = 0;
uint128_t u;
VALUE big;
if (n < 0) {
u = 1 + (uint128_t)(-(n + 1)); /* u = -n avoiding overflow */
neg = 1;
}
else {
u = n;
}
big = rb_uint128t2big(u);
if (neg) {
BIGNUM_SET_SIGN(big, 0);
}
return big;
}
#endif
VALUE
rb_cstr2inum(const char *str, int base)
{

Просмотреть файл

@ -1472,6 +1472,7 @@ RUBY_CHECK_SIZEOF(short)
RUBY_CHECK_SIZEOF(long, [int], [ILP LP])
RUBY_CHECK_SIZEOF(long long)
RUBY_CHECK_SIZEOF(__int64)
RUBY_CHECK_SIZEOF(__int128)
RUBY_CHECK_SIZEOF(off_t)
RUBY_CHECK_SIZEOF(void*, [int long "long long"], [ILP LP LLP])
RUBY_CHECK_SIZEOF(float)
@ -2007,6 +2008,7 @@ typedef $1 t; int s = sizeof(t) == 42;])],
["$ac_cv_sizeof_long"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])long"],
["$ac_cv_sizeof_long_long"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])long long"],
["$ac_cv_sizeof___int64"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])__int64"],
["$ac_cv_sizeof___int128"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])__int128"],
[ rb_cv_type_$1=no])])])
if test "${rb_cv_type_$1}" != no; then
AC_DEFINE([HAVE_]AS_TR_CPP($1), 1)
@ -2028,6 +2030,8 @@ RUBY_DEFINT(int32_t, 4)
RUBY_DEFINT(uint32_t, 4, unsigned)
RUBY_DEFINT(int64_t, 8)
RUBY_DEFINT(uint64_t, 8, unsigned)
RUBY_DEFINT(int128_t, 16)
RUBY_DEFINT(uint128_t, 16, unsigned)
RUBY_DEFINT(intptr_t, void*)
RUBY_DEFINT(uintptr_t, void*, unsigned)
RUBY_DEFINT(ssize_t, size_t, [], [@%:@include <sys/types.h>]) dnl may differ from int, so not use AC_TYPE_SSIZE_T.

Просмотреть файл

@ -1430,20 +1430,29 @@ opt_mult
{
if (FIXNUM_2_P(recv, obj) &&
BASIC_OP_UNREDEFINED_P(BOP_MULT, FIXNUM_REDEFINED_OP_FLAG)) {
long a, b;
a = FIX2LONG(recv);
long a = FIX2LONG(recv);
if (a == 0) {
val = recv;
}
else {
b = FIX2LONG(obj);
if (MUL_OVERFLOW_FIXNUM_P(a, b)) {
#ifdef HAVE_INT128_T
VALUE rb_int128t2big(int128_t n);
int128_t r = (int128_t)a * FIX2LONG(obj);
if (RB_FIXABLE(r)) {
val = LONG2FIX((long)r);
}
else {
val = rb_int128t2big(r);
}
#else
long b = FIX2LONG(obj);
if (MUL_OVERFLOW_FIXNUM_P(a, b)) {
val = rb_big_mul(rb_int2big(a), rb_int2big(b));
}
else {
}
else {
val = LONG2FIX(a * b);
}
}
#endif
}
}
else if (FLONUM_2_P(recv, obj) &&