From bd7a10e8fd6fda00f5119db6d9a3bf8bffee1210 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Wed, 19 Jun 2019 23:25:33 -0700 Subject: ash: refactor in light of gc bug. * arith.c (ash): Introduce smaller scopes and move variable initializations close to their use. The NUM case of argument a no longer falls through to the BGNUM case, and doesn't cons up a bignum object. Rather, a temporary mp_int is allocated, used and freed. The gc_hint added in the previous commit is now gone. --- arith.c | 62 ++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/arith.c b/arith.c index f374ddf4..db9b2deb 100644 --- a/arith.c +++ b/arith.c @@ -3198,9 +3198,7 @@ val ash(val a, val bits) { val self = ash_s; type_t ta = type(a); - cnum an, bn; - val b; - int hb; + cnum bn; const int num_bits = CHAR_BIT * sizeof (cnum) - TAG_SHIFT; mp_err mpe = MP_OKAY; @@ -3223,36 +3221,52 @@ val ash(val a, val bits) } else if (bn > 0) { switch (ta) { case NUM: - an = c_n(a); - hb = highest_significant_bit(an); - if (bn + hb < num_bits) - return num_fast(an << bn); - a = bignum(an); - /* fallthrough */ + { + cnum an = c_n(a); + int hb = highest_significant_bit(an); + if (bn + hb < num_bits) { + return num_fast(an << bn); + } else { + val b = make_bignum(); + mp_int tmp; + mp_init(&tmp); + mp_set_intptr(&tmp, an); + mpe = mp_shift(&tmp, mp(b), bn); + mp_clear(&tmp); + if (mpe != MP_OKAY) + break; + return normalize(b); + } + } case BGNUM: - if (bn < INT_MIN || bn > INT_MAX) + if (bn < INT_MIN || bn > INT_MAX) { goto bad4; - b = make_bignum(); - if ((mpe = mp_shift(mp(a), mp(b), bn)) != MP_OKAY) - break; - gc_hint(a); - return normalize(b); + } else { + val b = make_bignum(); + if ((mpe = mp_shift(mp(a), mp(b), bn)) != MP_OKAY) + break; + return normalize(b); + } default: goto bad3; } } else { switch (ta) { case NUM: - bn = -bn; - an = c_n(a); - if (bn <= num_bits) - return num_fast(an >> bn); - return num_fast(an >> num_bits); + { + cnum an = c_n(a); + bn = -bn; + if (bn <= num_bits) + return num_fast(an >> bn); + return num_fast(an >> num_bits); + } case BGNUM: - b = make_bignum(); - if ((mpe = mp_shift(mp(a), mp(b), bn)) != MP_OKAY) - break; - return normalize(b); + { + val b = make_bignum(); + if ((mpe = mp_shift(mp(a), mp(b), bn)) != MP_OKAY) + break; + return normalize(b); + } default: goto bad3; } -- cgit v1.2.3