mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-15 10:30:25 -08:00
Allocate bignum limbs in the AMC pool
Keep the mpz_t field in the Lisp_Bignum struct and the indirection so
that we don't need to change the bignum_val function. However, the
value._mp_d fields always points right after the mpz_t.
This patch also changes the peak memory usage for the pidigits benchmark
with MPS:
| | max rss | elapsed time |
|--------+-----------+--------------|
| before | 702316 KB | 16.99 s |
| after | 81128 KB | 17.15 s |
* src/bignum.h (struct Lisp_Bignum): Add room for the limb array.
* src/bignum.c (make_bignum_from_mpz): New.
(make_bignum_bits, make_bignum_str): Use it.
* src/igc.h (fix_bignum): New, needed to adjust the _mp_d field.
(fix_vector): Call it.
(finalize_bignum): Deleted.
(finalize_vector, maybe_finalize): No more finalization for bignums.
* src/pdumper.c (dump_bignum, dump_do_dump_relocation, dump_cold_bignum):
Adapt to new bignums.
This commit is contained in:
parent
43a000c31b
commit
13c058c358
4 changed files with 88 additions and 24 deletions
44
src/bignum.c
44
src/bignum.c
|
|
@ -66,6 +66,33 @@ double_to_integer (double d)
|
||||||
return make_integer_mpz ();
|
return make_integer_mpz ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_MPS
|
||||||
|
static struct Lisp_Bignum *
|
||||||
|
make_bignum_from_mpz (mpz_srcptr z)
|
||||||
|
{
|
||||||
|
size_t nlimbs = mpz_size (z);
|
||||||
|
const mp_limb_t *limbs = mpz_limbs_read (z);
|
||||||
|
size_t nbytes = (offsetof (struct Lisp_Bignum, limbs)
|
||||||
|
+ nlimbs * (sizeof *limbs) - header_size);
|
||||||
|
size_t roundup_size = max (GCALIGNMENT, word_size);
|
||||||
|
size_t nwords = ROUNDUP (nbytes, roundup_size) / word_size;
|
||||||
|
size_t rest_max = (1 << PSEUDOVECTOR_REST_BITS) - 1;
|
||||||
|
if (nwords > rest_max)
|
||||||
|
overflow_error ();
|
||||||
|
struct Lisp_Bignum *b
|
||||||
|
= (struct Lisp_Bignum *) allocate_pseudovector (nwords, 0, 0,
|
||||||
|
PVEC_BIGNUM);
|
||||||
|
eassert (vectorlike_nbytes (&b->header)
|
||||||
|
== ROUNDUP (nbytes + header_size, roundup_size));
|
||||||
|
eassert (nlimbs > 0);
|
||||||
|
memcpy (b->limbs, limbs, nlimbs * sizeof *limbs);
|
||||||
|
const mpz_t value = MPZ_ROINIT_N (b->limbs, z->_mp_size);
|
||||||
|
mpz_ptr p = b->value;
|
||||||
|
*p = *value;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Return a Lisp integer equal to mpz[0], which has BITS bits and which
|
/* Return a Lisp integer equal to mpz[0], which has BITS bits and which
|
||||||
must not be in fixnum range. Set mpz[0] to a junk value. */
|
must not be in fixnum range. Set mpz[0] to a junk value. */
|
||||||
static Lisp_Object
|
static Lisp_Object
|
||||||
|
|
@ -79,10 +106,14 @@ make_bignum_bits (size_t bits)
|
||||||
if (integer_width < bits && 2 * max (INTMAX_WIDTH, UINTMAX_WIDTH) < bits)
|
if (integer_width < bits && 2 * max (INTMAX_WIDTH, UINTMAX_WIDTH) < bits)
|
||||||
overflow_error ();
|
overflow_error ();
|
||||||
|
|
||||||
|
#ifdef HAVE_MPS
|
||||||
|
struct Lisp_Bignum *b = make_bignum_from_mpz (mpz[0]);
|
||||||
|
#else
|
||||||
struct Lisp_Bignum *b = ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Bignum,
|
struct Lisp_Bignum *b = ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Bignum,
|
||||||
PVEC_BIGNUM);
|
PVEC_BIGNUM);
|
||||||
mpz_init (b->value);
|
mpz_init (b->value);
|
||||||
mpz_swap (b->value, mpz[0]);
|
mpz_swap (b->value, mpz[0]);
|
||||||
|
#endif
|
||||||
return make_lisp_ptr (b, Lisp_Vectorlike);
|
return make_lisp_ptr (b, Lisp_Vectorlike);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -442,6 +473,18 @@ bignum_to_string (Lisp_Object num, int base)
|
||||||
of base-BASE digits, and a terminating null byte, and
|
of base-BASE digits, and a terminating null byte, and
|
||||||
the represented number must not be in fixnum range. */
|
the represented number must not be in fixnum range. */
|
||||||
|
|
||||||
|
#ifdef HAVE_MPS
|
||||||
|
Lisp_Object
|
||||||
|
make_bignum_str (char const *num, int base)
|
||||||
|
{
|
||||||
|
mpz_t tmp;
|
||||||
|
int check = mpz_init_set_str (tmp, num, base);
|
||||||
|
eassert (check == 0);
|
||||||
|
struct Lisp_Bignum *b = make_bignum_from_mpz (tmp);
|
||||||
|
mpz_clear (tmp);
|
||||||
|
return make_lisp_ptr (b, Lisp_Vectorlike);
|
||||||
|
}
|
||||||
|
#else
|
||||||
Lisp_Object
|
Lisp_Object
|
||||||
make_bignum_str (char const *num, int base)
|
make_bignum_str (char const *num, int base)
|
||||||
{
|
{
|
||||||
|
|
@ -452,6 +495,7 @@ make_bignum_str (char const *num, int base)
|
||||||
eassert (check == 0);
|
eassert (check == 0);
|
||||||
return make_lisp_ptr (b, Lisp_Vectorlike);
|
return make_lisp_ptr (b, Lisp_Vectorlike);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Check that X is a Lisp integer in the range LO..HI.
|
/* Check that X is a Lisp integer in the range LO..HI.
|
||||||
Return X's value as an intmax_t. */
|
Return X's value as an intmax_t. */
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,9 @@ struct Lisp_Bignum
|
||||||
{
|
{
|
||||||
struct vectorlike_header header;
|
struct vectorlike_header header;
|
||||||
mpz_t value;
|
mpz_t value;
|
||||||
|
#ifdef HAVE_MPS
|
||||||
|
mp_limb_t limbs[FLEXIBLE_ARRAY_MEMBER];
|
||||||
|
#endif
|
||||||
} GCALIGNED_STRUCT;
|
} GCALIGNED_STRUCT;
|
||||||
|
|
||||||
extern mpz_t mpz[5];
|
extern mpz_t mpz[5];
|
||||||
|
|
|
||||||
28
src/igc.c
28
src/igc.c
|
|
@ -103,7 +103,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
# ifndef HASH_Lisp_Finalizer_7DACDD23C5
|
# ifndef HASH_Lisp_Finalizer_7DACDD23C5
|
||||||
# error "struct Lisp_Finalizer changed"
|
# error "struct Lisp_Finalizer changed"
|
||||||
# endif
|
# endif
|
||||||
# ifndef HASH_Lisp_Bignum_8732048B98
|
# ifndef HASH_Lisp_Bignum_EC99943321
|
||||||
# error "struct Lisp_Bignum changed"
|
# error "struct Lisp_Bignum changed"
|
||||||
# endif
|
# endif
|
||||||
# ifndef HASH_Lisp_Float_4F10F019A4
|
# ifndef HASH_Lisp_Float_4F10F019A4
|
||||||
|
|
@ -2732,6 +2732,18 @@ fix_marker (mps_ss_t ss, struct Lisp_Marker *m)
|
||||||
return MPS_RES_OK;
|
return MPS_RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static mps_res_t
|
||||||
|
fix_bignum (mps_ss_t ss, struct Lisp_Bignum *b)
|
||||||
|
{
|
||||||
|
MPS_SCAN_BEGIN (ss)
|
||||||
|
{
|
||||||
|
mpz_ptr p = b->value;
|
||||||
|
p->_mp_d = b->limbs;
|
||||||
|
}
|
||||||
|
MPS_SCAN_END (ss);
|
||||||
|
return MPS_RES_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static mps_res_t
|
static mps_res_t
|
||||||
fix_finalizer (mps_ss_t ss, struct Lisp_Finalizer *f)
|
fix_finalizer (mps_ss_t ss, struct Lisp_Finalizer *f)
|
||||||
{
|
{
|
||||||
|
|
@ -2937,6 +2949,7 @@ fix_vector (mps_ss_t ss, struct Lisp_Vector *v)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PVEC_BIGNUM:
|
case PVEC_BIGNUM:
|
||||||
|
IGC_FIX_CALL_FN (ss, struct Lisp_Bignum, v, fix_bignum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PVEC_NATIVE_COMP_UNIT:
|
case PVEC_NATIVE_COMP_UNIT:
|
||||||
|
|
@ -3732,12 +3745,6 @@ igc_alloc_hash_table_user_test (void)
|
||||||
return ut;
|
return ut;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
finalize_bignum (struct Lisp_Bignum *n)
|
|
||||||
{
|
|
||||||
mpz_clear (n->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
finalize_font (struct font *font)
|
finalize_font (struct font *font)
|
||||||
{
|
{
|
||||||
|
|
@ -3846,10 +3853,6 @@ finalize_vector (mps_addr_t v)
|
||||||
/* Please use exhaustive switches, just to do me a favor :-). */
|
/* Please use exhaustive switches, just to do me a favor :-). */
|
||||||
switch (pseudo_vector_type (v))
|
switch (pseudo_vector_type (v))
|
||||||
{
|
{
|
||||||
case PVEC_BIGNUM:
|
|
||||||
finalize_bignum (v);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PVEC_FONT:
|
case PVEC_FONT:
|
||||||
finalize_font (v);
|
finalize_font (v);
|
||||||
break;
|
break;
|
||||||
|
|
@ -3934,6 +3937,7 @@ finalize_vector (mps_addr_t v)
|
||||||
case PVEC_TERMINAL:
|
case PVEC_TERMINAL:
|
||||||
case PVEC_MARKER:
|
case PVEC_MARKER:
|
||||||
case PVEC_MODULE_GLOBAL_REFERENCE:
|
case PVEC_MODULE_GLOBAL_REFERENCE:
|
||||||
|
case PVEC_BIGNUM:
|
||||||
igc_assert (!"finalization not implemented");
|
igc_assert (!"finalization not implemented");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -3994,7 +3998,6 @@ maybe_finalize (mps_addr_t ref, enum pvec_type tag)
|
||||||
}
|
}
|
||||||
switch (tag)
|
switch (tag)
|
||||||
{
|
{
|
||||||
case PVEC_BIGNUM:
|
|
||||||
case PVEC_FONT:
|
case PVEC_FONT:
|
||||||
case PVEC_THREAD:
|
case PVEC_THREAD:
|
||||||
case PVEC_MUTEX:
|
case PVEC_MUTEX:
|
||||||
|
|
@ -4044,6 +4047,7 @@ maybe_finalize (mps_addr_t ref, enum pvec_type tag)
|
||||||
case PVEC_PACKAGE:
|
case PVEC_PACKAGE:
|
||||||
#endif
|
#endif
|
||||||
case PVEC_MODULE_GLOBAL_REFERENCE:
|
case PVEC_MODULE_GLOBAL_REFERENCE:
|
||||||
|
case PVEC_BIGNUM:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2365,16 +2365,24 @@ struct bignum_reload_info
|
||||||
static dump_off
|
static dump_off
|
||||||
dump_bignum (struct dump_context *ctx, Lisp_Object object)
|
dump_bignum (struct dump_context *ctx, Lisp_Object object)
|
||||||
{
|
{
|
||||||
#if CHECK_STRUCTS && !defined (HASH_Lisp_Bignum_8732048B98)
|
#if CHECK_STRUCTS && !defined (HASH_Lisp_Bignum_EC99943321)
|
||||||
# error "Lisp_Bignum changed. See CHECK_STRUCTS comment in config.h."
|
# error "Lisp_Bignum changed. See CHECK_STRUCTS comment in config.h."
|
||||||
#endif
|
#endif
|
||||||
const struct Lisp_Bignum *bignum = XBIGNUM (object);
|
const struct Lisp_Bignum *bignum = XBIGNUM (object);
|
||||||
START_DUMP_PVEC (ctx, &bignum->header, struct Lisp_Bignum, out);
|
START_DUMP_PVEC (ctx, &bignum->header, struct Lisp_Bignum, out);
|
||||||
|
dump_off bignum_offset = ctx->offset;
|
||||||
static_assert (sizeof (out->value) >= sizeof (struct bignum_reload_info));
|
static_assert (sizeof (out->value) >= sizeof (struct bignum_reload_info));
|
||||||
dump_field_fixup_later (ctx, out, bignum, xbignum_val (object));
|
dump_field_fixup_later (ctx, out, bignum, xbignum_val (object));
|
||||||
dump_off bignum_offset = finish_dump_pvec (ctx, &out->header);
|
|
||||||
if (ctx->flags.dump_object_contents)
|
if (ctx->flags.dump_object_contents)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_MPS
|
||||||
|
eassert (out->value->_mp_alloc == 0);
|
||||||
|
DUMP_FIELD_COPY (out, bignum, value->_mp_size);
|
||||||
|
eassert (out->value->_mp_size != 0);
|
||||||
|
eassert (out->value->_mp_d == NULL);
|
||||||
|
size_t nlimbs = mpz_size (bignum->value);
|
||||||
|
memcpy (out->limbs, bignum->limbs, nlimbs * sizeof *out->limbs);
|
||||||
|
#else
|
||||||
/* Export the bignum into a blob in the cold section. */
|
/* Export the bignum into a blob in the cold section. */
|
||||||
dump_remember_cold_op (ctx, COLD_OP_BIGNUM, object);
|
dump_remember_cold_op (ctx, COLD_OP_BIGNUM, object);
|
||||||
|
|
||||||
|
|
@ -2386,7 +2394,7 @@ dump_bignum (struct dump_context *ctx, Lisp_Object object)
|
||||||
list3 (make_fixnum (DUMP_FIXUP_BIGNUM_DATA),
|
list3 (make_fixnum (DUMP_FIXUP_BIGNUM_DATA),
|
||||||
dump_off_to_lisp (value_offset),
|
dump_off_to_lisp (value_offset),
|
||||||
object));
|
object));
|
||||||
|
#endif
|
||||||
/* When we load the dump, slurp the data blob and turn it into a
|
/* When we load the dump, slurp the data blob and turn it into a
|
||||||
real bignum. Attach the relocation to the start of the
|
real bignum. Attach the relocation to the start of the
|
||||||
Lisp_Bignum instead of the actual mpz field so that the
|
Lisp_Bignum instead of the actual mpz field so that the
|
||||||
|
|
@ -2396,8 +2404,7 @@ dump_bignum (struct dump_context *ctx, Lisp_Object object)
|
||||||
list2 (make_fixnum (RELOC_BIGNUM),
|
list2 (make_fixnum (RELOC_BIGNUM),
|
||||||
dump_off_to_lisp (bignum_offset)));
|
dump_off_to_lisp (bignum_offset)));
|
||||||
}
|
}
|
||||||
|
return finish_dump_pvec (ctx, &out->header);
|
||||||
return bignum_offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static dump_off
|
static dump_off
|
||||||
|
|
@ -3688,10 +3695,6 @@ dump_cold_bignum (struct dump_context *ctx, Lisp_Object object)
|
||||||
eassert (sz_nlimbs < DUMP_OFF_MAX);
|
eassert (sz_nlimbs < DUMP_OFF_MAX);
|
||||||
dump_align_output (ctx, alignof (mp_limb_t));
|
dump_align_output (ctx, alignof (mp_limb_t));
|
||||||
dump_off nlimbs = (dump_off) sz_nlimbs;
|
dump_off nlimbs = (dump_off) sz_nlimbs;
|
||||||
# ifdef HAVE_MPS
|
|
||||||
char *dummy = (void *)igc_alloc_bytes (nlimbs * sizeof (mp_limb_t));
|
|
||||||
dump_igc_start_obj (ctx, IGC_OBJ_DUMPED_BIGNUM_DATA, dummy - sizeof (uint64_t));
|
|
||||||
# endif
|
|
||||||
Lisp_Object descriptor
|
Lisp_Object descriptor
|
||||||
= list2 (dump_off_to_lisp (ctx->offset),
|
= list2 (dump_off_to_lisp (ctx->offset),
|
||||||
dump_off_to_lisp (mpz_sgn (*n) < 0 ? -nlimbs : nlimbs));
|
dump_off_to_lisp (mpz_sgn (*n) < 0 ? -nlimbs : nlimbs));
|
||||||
|
|
@ -3701,9 +3704,6 @@ dump_cold_bignum (struct dump_context *ctx, Lisp_Object object)
|
||||||
mp_limb_t limb = mpz_getlimbn (*n, i);
|
mp_limb_t limb = mpz_getlimbn (*n, i);
|
||||||
dump_write (ctx, &limb, sizeof (limb));
|
dump_write (ctx, &limb, sizeof (limb));
|
||||||
}
|
}
|
||||||
# ifdef HAVE_MPS
|
|
||||||
dump_igc_finish_obj (ctx);
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_NATIVE_COMP
|
#ifdef HAVE_NATIVE_COMP
|
||||||
|
|
@ -5883,6 +5883,18 @@ dump_do_dump_relocation (const uintptr_t dump_base,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_MPS
|
||||||
|
case RELOC_BIGNUM:
|
||||||
|
{
|
||||||
|
struct Lisp_Bignum *b = dump_ptr (dump_base, reloc_offset);
|
||||||
|
mpz_ptr p = b->value;
|
||||||
|
eassert (p->_mp_alloc == 0);
|
||||||
|
eassert (p->_mp_size != 0);
|
||||||
|
eassert (p->_mp_d == NULL);
|
||||||
|
p->_mp_d = b->limbs;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
case RELOC_BIGNUM:
|
case RELOC_BIGNUM:
|
||||||
{
|
{
|
||||||
struct Lisp_Bignum *bignum = dump_ptr (dump_base, reloc_offset);
|
struct Lisp_Bignum *bignum = dump_ptr (dump_base, reloc_offset);
|
||||||
|
|
@ -5894,6 +5906,7 @@ dump_do_dump_relocation (const uintptr_t dump_base,
|
||||||
mpz_roinit_n (bignum->value, limbs, reload_info.nlimbs);
|
mpz_roinit_n (bignum->value, limbs, reload_info.nlimbs);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#ifdef HAVE_MPS
|
#ifdef HAVE_MPS
|
||||||
case RELOC_BUFFER:
|
case RELOC_BUFFER:
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue