From 1dfeabe2fa963919913993b65e6e7811b94f10cd Mon Sep 17 00:00:00 2001 From: Peter Bex Date: Thu, 9 Mar 2017 21:36:05 +0100 Subject: [PATCH] Avoid allocating scratchspace when reading fixnums. The code that handles reading digit streams into an integer is written to be as straightforward as possible. Currently this means it always allocates a bignum, even if the number is small enough to fit a fixnum. That way, we don't need to distinguish between these cases in the actual stream converter (str_to_bignum). We can improve on this a little bit by pre-allocating enough for a small bignum in the nursery, much like the C_s_a_u_i_integer_plus and friends do. This avoids malloc()ing a scratchspace just for the one small number, which will be free()d again as soon as the stack is full, resulting in a lot of needless thrashing. --- library.scm | 4 ++-- runtime.c | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/library.scm b/library.scm index 14fc9e5..284b653 100644 --- a/library.scm +++ b/library.scm @@ -1800,7 +1800,7 @@ EOF (end (or hashes digits))) (and-let* ((end) (num (##core#inline_allocate - ("C_s_a_i_digits_to_integer" 2) + ("C_s_a_i_digits_to_integer" 5) str start (car end) radix neg?))) (when hashes ; Eeewww. Feeling dirty yet? (set! seen-hashes? #t) @@ -1815,7 +1815,7 @@ EOF (end (scan-digits start))) (go-inexact!) (cons (##core#inline_allocate - ("C_s_a_i_digits_to_integer" 2) + ("C_s_a_i_digits_to_integer" 5) str start (car end) radix (eq? sign 'neg)) (cdr end))))))) (scan-decimal-tail ; The part after the decimal dot diff --git a/runtime.c b/runtime.c index e996559..af844df 100644 --- a/runtime.c +++ b/runtime.c @@ -10903,8 +10903,15 @@ C_s_a_i_digits_to_integer(C_word **ptr, C_word n, C_word str, C_word start, C_wo assert((radix > 1) && C_fitsinbignumhalfdigitp(radix)); nbits = (end - start) * C_ilen(radix - 1); - size = C_fix(C_BIGNUM_BITS_TO_DIGITS(nbits)); - result = C_allocate_scratch_bignum(ptr, size, negp, C_SCHEME_FALSE); + size = C_BIGNUM_BITS_TO_DIGITS(nbits); + if (size == 1) { + result = C_bignum1(ptr, C_truep(negp), 0); + } else if (size == 2) { + result = C_bignum2(ptr, C_truep(negp), 0, 0); + } else { + size = C_fix(size); + result = C_allocate_scratch_bignum(ptr, size, negp, C_SCHEME_FALSE); + } return str_to_bignum(result, s + start, s + end, radix); } -- 2.1.4