diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-06-22 12:48:45 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-06-22 12:48:45 +0000 |
commit | edc338875eaa5590b13aadb818a24e247249d616 (patch) | |
tree | cbb9e73f54ecbff02af1344c05c8a80a39adf39f | |
parent | 5bcfc7d2c76f69841b5199b73fe1788d0392d020 (diff) | |
download | ruby-edc338875eaa5590b13aadb818a24e247249d616.tar.gz |
* bignum.c (rb_integer_unpack): Don't allocate a Bignum if possible.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41569 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | bignum.c | 39 |
2 files changed, 39 insertions, 4 deletions
@@ -1,3 +1,7 @@ +Sat Jun 22 21:46:18 2013 Tanaka Akira <akr@fsij.org> + + * bignum.c (rb_integer_unpack): Don't allocate a Bignum if possible. + Sat Jun 22 21:03:58 2013 Tanaka Akira <akr@fsij.org> * pack.c (pack_unpack): Remove specialized unpackers for integers. @@ -1787,6 +1787,7 @@ rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t na int sign; int nlp_bits; BDIGIT *ds; + BDIGIT fixbuf[2] = { 0, 0 }; validate_integer_pack_format(numwords, wordsize, nails, flags, INTEGER_PACK_MSWORD_FIRST| @@ -1803,14 +1804,44 @@ rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t na if (LONG_MAX-1 < num_bdigits) rb_raise(rb_eArgError, "too big to unpack as an integer"); - val = bignew((long)num_bdigits, 0); - ds = BDIGITS(val); + if (num_bdigits <= numberof(fixbuf) && !(flags & INTEGER_PACK_FORCE_BIGNUM)) { + val = Qfalse; + ds = fixbuf; + } + else { + val = bignew((long)num_bdigits, 0); + ds = BDIGITS(val); + } sign = bary_unpack_internal(ds, num_bdigits, words, numwords, wordsize, nails, flags, nlp_bits); if (sign == -2) { - rb_big_resize(val, (long)num_bdigits+1); - BDIGITS(val)[num_bdigits] = 1; + if (val) { + rb_big_resize(val, (long)num_bdigits+1); + BDIGITS(val)[num_bdigits] = 1; + } + else if (num_bdigits == numberof(fixbuf)) { + val = bignew((long)num_bdigits+1, 0); + MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits); + BDIGITS(val)[num_bdigits++] = 1; + } + else { + ds[num_bdigits++] = 1; + } } + + if (!val) { + BDIGIT_DBL u = fixbuf[0] + BIGUP(fixbuf[1]); + if (u == 0) + return LONG2FIX(0); + if (0 < sign && POSFIXABLE(u)) + return LONG2FIX(u); + if (sign < 0 && (fixbuf[1] >> (BITSPERDIG-1)) == 0 && + NEGFIXABLE(-(BDIGIT_DBL_SIGNED)u)) + return LONG2FIX(-(BDIGIT_DBL_SIGNED)u); + val = bignew((long)num_bdigits, 0 <= sign); + MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits); + } + if ((flags & INTEGER_PACK_FORCE_BIGNUM) && sign != 0 && bary_zero_p(BDIGITS(val), RBIGNUM_LEN(val))) sign = 0; |