~ chicken-core (chicken-5) 137739038294e14dd290726fe0265b16e85a7ab7
commit 137739038294e14dd290726fe0265b16e85a7ab7
Author: Peter Bex <peter@more-magic.net>
AuthorDate: Thu Mar 9 21:36:05 2017 +0100
Commit: Evan Hanson <evhan@foldling.org>
CommitDate: Fri Mar 10 20:44:13 2017 +1300
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.
Signed-off-by: Evan Hanson <evhan@foldling.org>
diff --git a/library.scm b/library.scm
index 14fc9e5d..284b6530 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 e996559d..af844df4 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);
}
Trap