guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 69/69: Bignums avoid both custom GMP allocator and final


From: Andy Wingo
Subject: [Guile-commits] 69/69: Bignums avoid both custom GMP allocator and finalizers
Date: Fri, 7 Jan 2022 08:27:31 -0500 (EST)

wingo pushed a commit to branch wip-inline-digits
in repository guile.

commit a0d881f6597ba39f965aa542fd6abf2bbc20d5f4
Author: Andy Wingo <wingo@pobox.com>
AuthorDate: Fri Jan 7 14:01:52 2022 +0100

    Bignums avoid both custom GMP allocator and finalizers
    
    * libguile/deprecated.c (make_bignum): Move here from numbers.c, to
    support scm_i_long2big etc.
    (scm_i_big2dbl):
    (scm_i_long2big):
    (scm_i_ulong2big):
    (scm_i_clonebig):
    (scm_i_normbig): Deprecate.
    (scm_install_gmp_memory_functions): Deprecate, happily!  SCM bignums now
    have digits allocated inline with the bignum itself, so they are
    completely transparent to the GC already.  The price is that if GMP ever
    allocates digits via the MPZ API, those digits then have to be copied
    back into managed memory.  But we avoid having to install finalizers and
    we avoid having to muck with GMP's allocator.
    * libguile/numbers.c (scm_from_mpz): Use scm_integer_from_mpz.
    (scm_init_numbers): Never muck with GMP's allocators.
    * doc/ref/guile-invoke.texi (Environment Variables): Remove note about
    GUILE_INSTALL_GMP_MEMORY_FUNCTIONS.
    * meta/build-env.in: No need to set GUILE_INSTALL_GMP_MEMORY_FUNCTIONS.
---
 doc/ref/guile-invoke.texi |  15 +----
 libguile/deprecated.c     |  90 ++++++++++++++++++++++++++
 libguile/deprecated.h     |  15 ++++-
 libguile/numbers.c        | 161 +---------------------------------------------
 libguile/numbers.h        |  28 ++------
 meta/build-env.in         |   5 +-
 6 files changed, 113 insertions(+), 201 deletions(-)

diff --git a/doc/ref/guile-invoke.texi b/doc/ref/guile-invoke.texi
index 92208d559..856bce7b8 100644
--- a/doc/ref/guile-invoke.texi
+++ b/doc/ref/guile-invoke.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Guile Reference Manual.
-@c Copyright (C) 1996-1997,2000-2005,2010-2011,2013-2014,2016,2019,2021
+@c Copyright (C) 1996-1997,2000-2005,2010-2011,2013-2014,2016,2019,2021-2022
 @c   Free Software Foundation, Inc.
 @c See the file guile.texi for copying conditions.
 
@@ -424,19 +424,6 @@ Guile uses the environment variable @env{HOME}, the name 
of your home
 directory, to locate various files, such as @file{.guile} or
 @file{.guile_history}.
 
-@item GUILE_INSTALL_GMP_MEMORY_FUNCTIONS
-@vindex GUILE_INSTALL_GMP_MEMORY_FUNCTIONS
-Guile uses the GNU multi-precision (GMP) library to implement its bigint
-support.  It can use an included minimal version of GMP, or the system
-version, which may be more optimal.  If Guile is the sole user of GMP in
-the process, Guile can tell GMP to allocate its digits using
-garbage-collected memory.  This can be significantly faster.  However
-this approach is unsafe if there are other libraries loaded that use
-libgmp, such as the GnuTLS library.  The default is for Guile to do the
-fastest safe thing: use the garbage collector for GMP when using the
-included ``mini-GMP'', but not otherwise.  Set this variable to nonzero
-to force GMP to use garbage-collected memory, even when using system GC.
-
 @item GUILE_JIT_THRESHOLD
 @vindex GUILE_JIT_THRESHOLD
 Guile has a just-in-time (JIT) code generator that makes running Guile
diff --git a/libguile/deprecated.c b/libguile/deprecated.c
index 0e0c20f28..8622e3bb8 100644
--- a/libguile/deprecated.c
+++ b/libguile/deprecated.c
@@ -36,6 +36,7 @@
 #include "dynl.h"
 #include "eval.h"
 #include "foreign.h"
+#include "finalizers.h"
 #include "generalized-vectors.h"
 #include "gc.h"
 #include "gsubr.h"
@@ -692,6 +693,95 @@ SCM_DEFINE (scm_dynamic_unlink, "dynamic-unlink", 1, 0, 0, 
(SCM obj), "")
 
 
 
+static void
+finalize_bignum (void *ptr, void *data)
+{
+  SCM bignum;
+
+  bignum = SCM_PACK_POINTER (ptr);
+  mpz_clear (SCM_I_BIG_MPZ (bignum));
+}
+
+static SCM
+make_bignum (void)
+{
+  scm_t_bits *p;
+
+  /* Allocate one word for the type tag and enough room for an `mpz_t'.  */
+  p = scm_gc_malloc_pointerless (sizeof (scm_t_bits) + sizeof (mpz_t),
+                                 "bignum");
+  p[0] = scm_tc16_big;
+  scm_i_set_finalizer (p, finalize_bignum, NULL);
+
+  return SCM_PACK (p);
+}
+
+/* scm_i_big2dbl() rounds to the closest representable double,
+   in accordance with R5RS exact->inexact.  */
+double
+scm_i_big2dbl (SCM b)
+{
+  scm_c_issue_deprecation_warning
+    ("scm_i_big2dbl is deprecated.  Use scm_to_double instead.");
+  return scm_to_double (b);
+}
+
+SCM
+scm_i_long2big (long x)
+{
+  scm_c_issue_deprecation_warning
+    ("scm_i_long2big is deprecated.  Use scm_from_long instead.");
+  /* Return a newly created bignum initialized to X. */
+  SCM z = make_bignum ();
+  mpz_init_set_si (SCM_I_BIG_MPZ (z), x);
+  return z;
+}
+
+SCM
+scm_i_ulong2big (unsigned long x)
+{
+  scm_c_issue_deprecation_warning
+    ("scm_i_ulong2big is deprecated.  Use scm_from_ulong instead.");
+  /* Return a newly created bignum initialized to X. */
+  SCM z = make_bignum ();
+  mpz_init_set_ui (SCM_I_BIG_MPZ (z), x);
+  return z;
+}
+
+SCM
+scm_i_clonebig (SCM src_big, int same_sign_p)
+{
+  scm_c_issue_deprecation_warning
+    ("scm_i_clonebig is deprecated.  Use scm_to_mpz/scm_from_mpz instead.");
+  /* Copy src_big's value, negate it if same_sign_p is false, and return. */
+  SCM z = make_bignum ();
+  scm_to_mpz (src_big, SCM_I_BIG_MPZ (z));
+  if (!same_sign_p)
+    mpz_neg (SCM_I_BIG_MPZ (z), SCM_I_BIG_MPZ (z));
+  return z;
+}
+
+SCM
+scm_i_normbig (SCM b)
+{
+  scm_c_issue_deprecation_warning
+    ("scm_i_normbig is deprecated.  Direct bignum bit manipulation is not "
+     "supported.");
+  /* convert a big back to a fixnum if it'll fit */
+  /* presume b is a bignum */
+  if (mpz_fits_slong_p (SCM_I_BIG_MPZ (b)))
+    {
+      scm_t_inum val = mpz_get_si (SCM_I_BIG_MPZ (b));
+      if (SCM_FIXABLE (val))
+        b = SCM_I_MAKINUM (val);
+    }
+  return b;
+}
+
+int scm_install_gmp_memory_functions;
+
+
+
 void
 scm_i_init_deprecated ()
 {
diff --git a/libguile/deprecated.h b/libguile/deprecated.h
index a062cbecb..be5b55676 100644
--- a/libguile/deprecated.h
+++ b/libguile/deprecated.h
@@ -1,7 +1,7 @@
 #ifndef SCM_DEPRECATED_H
 #define SCM_DEPRECATED_H
 
-/* Copyright 2003-2007,2009-2018,2020,2021
+/* Copyright 2003-2007,2009-2018,2020-2022
      Free Software Foundation, Inc.
 
    This file is part of Guile.
@@ -146,6 +146,19 @@ SCM_DEPRECATED SCM scm_copy_tree (SCM obj);
 
 SCM_DEPRECATED SCM scm_dynamic_unlink (SCM obj);
 
+/* Each bignum is just an mpz_t stored in a double cell starting at word 1. */
+#if defined BUILDING_LIBGUILE || SCM_ENABLE_MINI_GMP == 0
+#define SCM_I_BIG_MPZ(x) (*((mpz_t *) (SCM_CELL_OBJECT_LOC((x),1))))
+#endif
+
+SCM_DEPRECATED int scm_install_gmp_memory_functions;
+SCM_DEPRECATED SCM scm_i_normbig (SCM x);
+SCM_DEPRECATED double scm_i_big2dbl (SCM b);
+SCM_DEPRECATED SCM scm_i_long2big (long n);
+SCM_DEPRECATED SCM scm_i_ulong2big (unsigned long n);
+SCM_DEPRECATED SCM scm_i_clonebig (SCM src_big, int same_sign_p);
+
+
 void scm_i_init_deprecated (void);
 
 #endif
diff --git a/libguile/numbers.c b/libguile/numbers.c
index e62646ea2..20d525408 100644
--- a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ -160,25 +160,6 @@ VARARG_MPZ_ITERATOR (mpz_clear)
 */
 /* the macro above will not work as is with fractions */
 
-
-/* In the context of Guile, it's most efficient for GMP to use libgc to
-   allocate MPZ values.  That way Guile doesn't need to install
-   finalizers, which have significant overhead.  Using libgc to allocate
-   digits also allows Guile's GC to adequately measure the memory cost
-   of MPZ values.
-
-   However, if the Guile process is linked to some other user of GMP,
-   then probably the references from the other user of GMP to MPZ values
-   aren't visible to the garbage collector.  So libgc could prematurely
-   collect values from that other GMP user.
-
-   This isn't theoretical -- it happens for Guile-GnuTLS.  GnuTLS uses
-   GMP, and so does Guile.  But if Guile installs libgc as the allocator
-   for MPZ values, we break GnuTLS.
-
-   Therefore we only install libgc as the GMP allocator if we are using
-   mini-gmp, which we know isn't shared with any external library.  */
-int scm_install_gmp_memory_functions = SCM_ENABLE_MINI_GMP;
 static SCM flo0;
 static SCM exactly_one_half;
 static SCM flo_log10e;
@@ -234,132 +215,6 @@ scm_from_complex_double (complex double z)
 
 
 
-/* Clear the `mpz_t' embedded in bignum PTR.  */
-static void
-finalize_bignum (void *ptr, void *data)
-{
-  SCM bignum;
-
-  bignum = SCM_PACK_POINTER (ptr);
-  mpz_clear (SCM_I_BIG_MPZ (bignum));
-}
-
-/* The next three functions (custom_libgmp_*) are passed to
-   mp_set_memory_functions (in GMP) so that memory used by the digits
-   themselves is known to the garbage collector.  This is needed so
-   that GC will be run at appropriate times.  Otherwise, a program which
-   creates many large bignums would malloc a huge amount of memory
-   before the GC runs. */
-static void *
-custom_gmp_malloc (size_t alloc_size)
-{
-  return scm_gc_malloc_pointerless (alloc_size, "GMP");
-}
-
-static void *
-custom_gmp_realloc (void *old_ptr, size_t old_size, size_t new_size)
-{
-  return scm_gc_realloc (old_ptr, old_size, new_size, "GMP");
-}
-
-static void
-custom_gmp_free (void *ptr, size_t size)
-{
-  /* Do nothing: all memory allocated by GMP is under GC control and
-     will be freed when needed.  */
-}
-
-
-/* Return a new uninitialized bignum.  */
-static inline SCM
-make_bignum (void)
-{
-  scm_t_bits *p;
-
-  /* Allocate one word for the type tag and enough room for an `mpz_t'.  */
-  p = scm_gc_malloc (sizeof (scm_t_bits) + sizeof (mpz_t),
-                     "bignum");
-  p[0] = scm_tc16_big;
-
-  /* When the 'custom_gmp_*' functions are in use, no need to set a
-     finalizer since allocated memory is under GC control.  In other
-     cases, set a finalizer to call 'mpz_clear', which is expensive.  */
-  if (!scm_install_gmp_memory_functions)
-    scm_i_set_finalizer (p, finalize_bignum, NULL);
-
-  return SCM_PACK (p);
-}
-
-
-SCM
-scm_i_long2big (long x)
-{
-  /* Return a newly created bignum initialized to X. */
-  SCM z = make_bignum ();
-  mpz_init_set_si (SCM_I_BIG_MPZ (z), x);
-  return z;
-}
-
-SCM
-scm_i_ulong2big (unsigned long x)
-{
-  /* Return a newly created bignum initialized to X. */
-  SCM z = make_bignum ();
-  mpz_init_set_ui (SCM_I_BIG_MPZ (z), x);
-  return z;
-}
-
-SCM
-scm_i_clonebig (SCM src_big, int same_sign_p)
-{
-  /* Copy src_big's value, negate it if same_sign_p is false, and return. */
-  SCM z = make_bignum ();
-  mpz_init_set (SCM_I_BIG_MPZ (z), SCM_I_BIG_MPZ (src_big));
-  if (!same_sign_p)
-    mpz_neg (SCM_I_BIG_MPZ (z), SCM_I_BIG_MPZ (z));
-  return z;
-}
-
-/* scm_i_big2dbl() rounds to the closest representable double,
-   in accordance with R5RS exact->inexact.  */
-double
-scm_i_big2dbl (SCM b)
-{
-  return scm_integer_to_double_z (scm_bignum (b));
-}
-
-SCM
-scm_i_normbig (SCM b)
-{
-  /* convert a big back to a fixnum if it'll fit */
-  /* presume b is a bignum */
-  if (mpz_fits_slong_p (SCM_I_BIG_MPZ (b)))
-    {
-      scm_t_inum val = mpz_get_si (SCM_I_BIG_MPZ (b));
-      if (SCM_FIXABLE (val))
-        b = SCM_I_MAKINUM (val);
-    }
-  return b;
-}
-
-static SCM_C_INLINE_KEYWORD SCM
-scm_i_mpz2num (mpz_t b)
-{
-  /* convert a mpz number to a SCM number. */
-  if (mpz_fits_slong_p (b))
-    {
-      scm_t_inum val = mpz_get_si (b);
-      if (SCM_FIXABLE (val))
-        return SCM_I_MAKINUM (val);
-    }
-
-  {
-    SCM z = make_bignum ();
-    mpz_init_set (SCM_I_BIG_MPZ (z), b);
-    return z;
-  }
-}
-
 /* Make the ratio NUMERATOR/DENOMINATOR, where:
     1. NUMERATOR and DENOMINATOR are exact integers
     2. NUMERATOR and DENOMINATOR are reduced to lowest terms: gcd(n,d) == 1 */
@@ -6938,7 +6793,7 @@ scm_to_mpz (SCM val, mpz_t rop)
 SCM
 scm_from_mpz (mpz_t val)
 {
-  return scm_i_mpz2num (val);
+  return scm_integer_from_mpz (val);
 }
 
 int
@@ -7324,20 +7179,6 @@ SCM_PRIMITIVE_GENERIC (scm_sqrt, "sqrt", 1, 0, 0,
 void
 scm_init_numbers ()
 {
-  /* Give the user the chance to force the use of libgc to manage gmp
-     digits, if we know there are no external GMP users in this process.
-     Can be an important optimization for those who link external GMP,
-     before we switch to the MPN API.  */
-  if (!SCM_ENABLE_MINI_GMP)
-    scm_install_gmp_memory_functions
-      = scm_getenv_int ("GUILE_INSTALL_GMP_MEMORY_FUNCTIONS",
-                        scm_install_gmp_memory_functions);
-
-  if (scm_install_gmp_memory_functions)
-    mp_set_memory_functions (custom_gmp_malloc,
-                             custom_gmp_realloc,
-                             custom_gmp_free);
-
   /* It may be possible to tune the performance of some algorithms by using
    * the following constants to avoid the creation of bignums.  Please, before
    * using these values, remember the two rules of program optimization:
diff --git a/libguile/numbers.h b/libguile/numbers.h
index 80bc11720..fdb446e1a 100644
--- a/libguile/numbers.h
+++ b/libguile/numbers.h
@@ -1,7 +1,7 @@
 #ifndef SCM_NUMBERS_H
 #define SCM_NUMBERS_H
 
-/* Copyright 1995-1996,1998,2000-2006,2008-2011,2013-2014,2016-2018,2021,2022
+/* Copyright 1995-1996,1998,2000-2006,2008-2011,2013-2014,2016-2018,2021-2022
      Free Software Foundation, Inc.
 
    This file is part of Guile.
@@ -168,11 +168,6 @@ typedef long scm_t_inum;
 #define SCM_COMPLEX_REAL(x) (((scm_t_complex *) SCM2PTR (x))->real)
 #define SCM_COMPLEX_IMAG(x) (((scm_t_complex *) SCM2PTR (x))->imag)
 
-/* Each bignum is just an mpz_t stored in a double cell starting at word 1. */
-#if defined BUILDING_LIBGUILE || SCM_ENABLE_MINI_GMP == 0
-#define SCM_I_BIG_MPZ(x) (*((mpz_t *) (SCM_CELL_OBJECT_LOC((x),1))))
-#endif
-
 #define SCM_BIGP(x) (SCM_HAS_TYP16 (x, scm_tc16_big))
 
 #define SCM_NUMBERP(x) (SCM_I_INUMP(x) || SCM_NUMP(x))
@@ -203,7 +198,6 @@ typedef struct scm_t_complex
   double imag;
 } scm_t_complex;
 
-
 
 
 SCM_API SCM scm_exact_p (SCM x);
@@ -346,13 +340,6 @@ SCM_INTERNAL SCM scm_i_product (SCM x, SCM y, SCM rest);
 SCM_INTERNAL SCM scm_i_divide (SCM x, SCM y, SCM rest);
 SCM_INTERNAL SCM scm_i_exact_integer_sqrt (SCM k);
 
-/* bignum internal functions */
-SCM_API /* FIXME: not internal */ SCM scm_i_normbig (SCM x);
-SCM_API /* FIXME: not internal */ double scm_i_big2dbl (SCM b);
-SCM_API /* FIXME: not internal */ SCM scm_i_long2big (long n);
-SCM_API /* FIXME: not internal */ SCM scm_i_ulong2big (unsigned long n);
-SCM_API /* FIXME: not internal */ SCM scm_i_clonebig (SCM src_big, int 
same_sign_p);
-
 /* ratio functions */
 SCM_API SCM scm_rationalize (SCM x, SCM err);
 SCM_API SCM scm_numerator (SCM z);
@@ -380,13 +367,13 @@ SCM_API SCM scm_from_signed_integer (intmax_t val);
 SCM_API SCM scm_from_unsigned_integer (uintmax_t val);
 
 SCM_API intmax_t scm_to_signed_integer (SCM val,
-                                           intmax_t min,
-                                           intmax_t max);
+                                        intmax_t min,
+                                        intmax_t max);
 SCM_API uintmax_t scm_to_unsigned_integer (SCM val,
-                                              uintmax_t min,
-                                              uintmax_t max);
+                                           uintmax_t min,
+                                           uintmax_t max);
 
-SCM_API int8_t   scm_to_int8     (SCM x);
+SCM_API int8_t       scm_to_int8     (SCM x);
 SCM_API SCM          scm_from_int8   (int8_t x);
 
 SCM_API uint8_t      scm_to_uint8    (SCM x);
@@ -607,9 +594,6 @@ SCM_API double scm_c_angle (SCM z);
 
 SCM_API int scm_is_number (SCM val);
 
-/* If nonzero, tell gmp to use GC_malloc for its allocations.  */
-SCM_API int scm_install_gmp_memory_functions;
-
 SCM_INTERNAL void scm_init_numbers (void);
 
 
diff --git a/meta/build-env.in b/meta/build-env.in
index 299b44f99..b48f9c245 100644
--- a/meta/build-env.in
+++ b/meta/build-env.in
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-#      Copyright (C) 2003, 2006, 2008-2012, 2016, 2017, 2021 Free Software 
Foundation
+#      Copyright (C) 2003, 2006, 2008-2012, 2016, 2017, 2021, 2022 Free 
Software Foundation
 #
 #   This file is part of GNU Guile.
 #
@@ -90,9 +90,6 @@ done
 export LTDL_LIBRARY_PATH
 export DYLD_LIBRARY_PATH
 
-GUILE_INSTALL_GMP_MEMORY_FUNCTIONS=1
-export GUILE_INSTALL_GMP_MEMORY_FUNCTIONS
-
 if [ x"$PKG_CONFIG_PATH" = x ]
 then
     PKG_CONFIG_PATH="${top_builddir}/meta"



reply via email to

[Prev in Thread] Current Thread [Next in Thread]