gh-100227: Move the dtoa State to PyInterpreterState (gh-102331)

https://github.com/python/cpython/issues/100227
This commit is contained in:
Eric Snow 2023-02-28 13:14:40 -07:00 committed by GitHub
parent b5ff382433
commit f300a1fa4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 39 additions and 17 deletions

View File

@ -24,10 +24,11 @@ Bigint {
#ifdef Py_USING_MEMORY_DEBUGGER
struct _dtoa_runtime_state {
struct _dtoa_state {
int _not_used;
};
#define _dtoa_runtime_state_INIT {0}
#define _dtoa_interp_state_INIT(INTERP) \
{0}
#else // !Py_USING_MEMORY_DEBUGGER
@ -40,7 +41,7 @@ struct _dtoa_runtime_state {
#define Bigint_PREALLOC_SIZE \
((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
struct _dtoa_runtime_state {
struct _dtoa_state {
/* p5s is a linked list of powers of 5 of the form 5**(2**i), i >= 2 */
// XXX This should be freed during runtime fini.
struct Bigint *p5s;
@ -48,9 +49,9 @@ struct _dtoa_runtime_state {
double preallocated[Bigint_PREALLOC_SIZE];
double *preallocated_next;
};
#define _dtoa_runtime_state_INIT(runtime) \
#define _dtoa_state_INIT(INTERP) \
{ \
.preallocated_next = runtime.dtoa.preallocated, \
.preallocated_next = (INTERP)->dtoa.preallocated, \
}
#endif // !Py_USING_MEMORY_DEBUGGER

View File

@ -16,6 +16,7 @@ extern "C" {
#include "pycore_code.h" // struct callable_cache
#include "pycore_context.h" // struct _Py_context_state
#include "pycore_dict_state.h" // struct _Py_dict_state
#include "pycore_dtoa.h" // struct _dtoa_state
#include "pycore_exceptions.h" // struct _Py_exc_state
#include "pycore_floatobject.h" // struct _Py_float_state
#include "pycore_function.h" // FUNC_MAX_WATCHERS
@ -139,6 +140,7 @@ struct _is {
struct _Py_unicode_state unicode;
struct _Py_float_state float_state;
struct _Py_long_state long_state;
struct _dtoa_state dtoa;
/* Using a cache is very effective since typically only a single slice is
created and then deleted again. */
PySliceObject *slice_cache;

View File

@ -11,7 +11,6 @@ extern "C" {
#include "pycore_atomic.h" /* _Py_atomic_address */
#include "pycore_ceval_state.h" // struct _ceval_runtime_state
#include "pycore_dict_state.h" // struct _Py_dict_runtime_state
#include "pycore_dtoa.h" // struct _dtoa_runtime_state
#include "pycore_floatobject.h" // struct _Py_float_runtime_state
#include "pycore_faulthandler.h" // struct _faulthandler_runtime_state
#include "pycore_function.h" // struct _func_runtime_state
@ -141,7 +140,6 @@ typedef struct pyruntimestate {
struct _ceval_runtime_state ceval;
struct _gilstate_runtime_state gilstate;
struct _getargs_runtime_state getargs;
struct _dtoa_runtime_state dtoa;
struct _fileutils_state fileutils;
struct _faulthandler_runtime_state faulthandler;
struct _tracemalloc_runtime_state tracemalloc;

View File

@ -53,7 +53,6 @@ extern "C" {
.gilstate = { \
.check_enabled = 1, \
}, \
.dtoa = _dtoa_runtime_state_INIT(runtime), \
.fileutils = { \
.force_ascii = -1, \
}, \
@ -94,10 +93,10 @@ extern "C" {
}, \
}, \
}, \
._main_interpreter = _PyInterpreterState_INIT, \
._main_interpreter = _PyInterpreterState_INIT(runtime._main_interpreter), \
}
#define _PyInterpreterState_INIT \
#define _PyInterpreterState_INIT(INTERP) \
{ \
.id_refcount = -1, \
.imports = IMPORTS_INIT, \
@ -113,6 +112,7 @@ extern "C" {
{ .threshold = 10, }, \
}, \
}, \
.dtoa = _dtoa_state_INIT(&(INTERP)), \
.static_objects = { \
.singletons = { \
._not_used = 1, \

View File

@ -119,7 +119,7 @@
#include "Python.h"
#include "pycore_dtoa.h" // _PY_SHORT_FLOAT_REPR
#include "pycore_runtime.h" // _PyRuntime
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include <stdlib.h> // exit()
/* if _PY_SHORT_FLOAT_REPR == 0, then don't even try to compile
@ -339,9 +339,9 @@ typedef struct Bigint Bigint;
Bfree to PyMem_Free. Investigate whether this has any significant
performance on impact. */
#define freelist _PyRuntime.dtoa.freelist
#define private_mem _PyRuntime.dtoa.preallocated
#define pmem_next _PyRuntime.dtoa.preallocated_next
#define freelist interp->dtoa.freelist
#define private_mem interp->dtoa.preallocated
#define pmem_next interp->dtoa.preallocated_next
/* Allocate space for a Bigint with up to 1<<k digits */
@ -351,6 +351,7 @@ Balloc(int k)
int x;
Bigint *rv;
unsigned int len;
PyInterpreterState *interp = _PyInterpreterState_GET();
if (k <= Bigint_Kmax && (rv = freelist[k]))
freelist[k] = rv->next;
@ -385,6 +386,7 @@ Bfree(Bigint *v)
if (v->k > Bigint_Kmax)
FREE((void*)v);
else {
PyInterpreterState *interp = _PyInterpreterState_GET();
v->next = freelist[v->k];
freelist[v->k] = v;
}
@ -692,7 +694,8 @@ pow5mult(Bigint *b, int k)
if (!(k >>= 2))
return b;
p5 = _PyRuntime.dtoa.p5s;
PyInterpreterState *interp = _PyInterpreterState_GET();
p5 = interp->dtoa.p5s;
if (!p5) {
/* first time */
p5 = i2b(625);
@ -700,7 +703,7 @@ pow5mult(Bigint *b, int k)
Bfree(b);
return NULL;
}
_PyRuntime.dtoa.p5s = p5;
interp->dtoa.p5s = p5;
p5->next = 0;
}
for(;;) {

View File

@ -3,7 +3,8 @@
#include "Python.h"
#include "pycore_ceval.h"
#include "pycore_code.h" // stats
#include "pycore_code.h" // stats
#include "pycore_dtoa.h" // _dtoa_state_INIT()
#include "pycore_frame.h"
#include "pycore_initconfig.h"
#include "pycore_object.h" // _PyType_InitCache()
@ -618,6 +619,18 @@ free_interpreter(PyInterpreterState *interp)
e.g. by PyMem_RawCalloc() or memset(), or otherwise pre-initialized.
The runtime state is not manipulated. Instead it is assumed that
the interpreter is getting added to the runtime.
Note that the main interpreter was statically initialized as part
of the runtime and most state is already set properly. That leaves
a small number of fields to initialize dynamically, as well as some
that are initialized lazily.
For subinterpreters we memcpy() the main interpreter in
PyInterpreterState_New(), leaving it in the same mostly-initialized
state. The only difference is that the interpreter has some
self-referential state that is statically initializexd to the
main interpreter. We fix those fields here, in addition
to the other dynamically initialized fields.
*/
static void
@ -645,6 +658,11 @@ init_interpreter(PyInterpreterState *interp,
PyConfig_InitPythonConfig(&interp->config);
_PyType_InitCache(interp);
if (interp != &runtime->_main_interpreter) {
/* Fix the self-referential, statically initialized fields. */
interp->dtoa = (struct _dtoa_state)_dtoa_state_INIT(interp);
}
interp->_initialized = 1;
}