From 5bd1059184b154d339f1bd53d23c98b5bcf14c8c Mon Sep 17 00:00:00 2001 From: junyixie Date: Sat, 13 Mar 2021 21:25:14 +0800 Subject: bpo-40521: Make dtoa bigint free list per-interpreter (GH-24821) --- Include/internal/pycore_dtoa.h | 16 ++++++++++++++++ Include/internal/pycore_interp.h | 4 ++++ Python/dtoa.c | 36 +++++++++++++++++++----------------- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/Include/internal/pycore_dtoa.h b/Include/internal/pycore_dtoa.h index 3faf8cf..0f61e75 100644 --- a/Include/internal/pycore_dtoa.h +++ b/Include/internal/pycore_dtoa.h @@ -1,4 +1,6 @@ #ifndef PY_NO_SHORT_FLOAT_REPR +#ifndef Py_INTERNAL_DTOA_H +#define Py_INTERNAL_DTOA_H #ifdef __cplusplus extern "C" { #endif @@ -17,7 +19,21 @@ PyAPI_FUNC(void) _Py_dg_freedtoa(char *s); PyAPI_FUNC(double) _Py_dg_stdnan(int sign); PyAPI_FUNC(double) _Py_dg_infinity(int sign); +#define _PyDtoa_Kmax 7 + +typedef uint32_t _PyDtoa_ULong; +typedef int32_t _PyDtoa_Long; +typedef uint64_t _PyDtoa_ULLong; + +struct +_PyDtoa_Bigint { + struct _PyDtoa_Bigint *next; + int k, maxwds, sign, wds; + _PyDtoa_ULong x[1]; +}; + #ifdef __cplusplus } #endif +#endif /* !Py_INTERNAL_DTOA_H */ #endif /* !PY_NO_SHORT_FLOAT_REPR */ diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 477cbf0..ea770da 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -13,6 +13,7 @@ extern "C" { #include "pycore_gil.h" // struct _gil_runtime_state #include "pycore_gc.h" // struct _gc_runtime_state #include "pycore_warnings.h" // struct _warnings_runtime_state +#include "pycore_dtoa.h" struct _pending_calls { PyThread_type_lock lock; @@ -321,6 +322,9 @@ struct _is { struct ast_state ast; struct type_cache type_cache; +#ifndef PY_NO_SHORT_FLOAT_REPR + struct _PyDtoa_Bigint *dtoa_freelist[_PyDtoa_Kmax + 1]; +#endif }; extern void _PyInterpreterState_ClearModules(PyInterpreterState *interp); diff --git a/Python/dtoa.c b/Python/dtoa.c index e629b29..c7002e5 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -119,6 +119,16 @@ #include "Python.h" #include "pycore_dtoa.h" +#include "pycore_interp.h" +#include "pycore_pystate.h" + +#define ULong _PyDtoa_ULong +#define Long _PyDtoa_Long +#define ULLong _PyDtoa_ULLong +#define Kmax _PyDtoa_Kmax + +typedef struct _PyDtoa_Bigint Bigint; + /* if PY_NO_SHORT_FLOAT_REPR is defined, then don't even try to compile the following code */ @@ -154,11 +164,6 @@ #error "doubles and ints have incompatible endianness" #endif - -typedef uint32_t ULong; -typedef int32_t Long; -typedef uint64_t ULLong; - #undef DEBUG #ifdef Py_DEBUG #define DEBUG @@ -297,8 +302,6 @@ BCinfo { #define FFFFFFFF 0xffffffffUL -#define Kmax 7 - /* struct Bigint is used to represent arbitrary-precision integers. These integers are stored in sign-magnitude format, with the magnitude stored as an array of base 2**32 digits. Bigints are always normalized: if x is a @@ -321,14 +324,6 @@ BCinfo { significant (x[0]) to most significant (x[wds-1]). */ -struct -Bigint { - struct Bigint *next; - int k, maxwds, sign, wds; - ULong x[1]; -}; - -typedef struct Bigint Bigint; #ifndef Py_USING_MEMORY_DEBUGGER @@ -351,7 +346,13 @@ typedef struct Bigint Bigint; Bfree to PyMem_Free. Investigate whether this has any significant performance on impact. */ -static Bigint *freelist[Kmax+1]; + +/* Get Bigint freelist from interpreter */ +static Bigint ** +get_freelist(void) { + PyInterpreterState *interp = _PyInterpreterState_GET(); + return interp->dtoa_freelist; +} /* Allocate space for a Bigint with up to 1<next; else { @@ -393,6 +394,7 @@ Bfree(Bigint *v) if (v->k > Kmax) FREE((void*)v); else { + Bigint **freelist = get_freelist(); v->next = freelist[v->k]; freelist[v->k] = v; } -- cgit v0.12