mirror of
https://github.com/python/cpython.git
synced 2025-09-19 23:20:25 +00:00
gh-100227: Move the dtoa State to PyInterpreterState (gh-102331)
https://github.com/python/cpython/issues/100227
This commit is contained in:
parent
b5ff382433
commit
f300a1fa4c
6 changed files with 39 additions and 17 deletions
|
@ -24,10 +24,11 @@ Bigint {
|
||||||
|
|
||||||
#ifdef Py_USING_MEMORY_DEBUGGER
|
#ifdef Py_USING_MEMORY_DEBUGGER
|
||||||
|
|
||||||
struct _dtoa_runtime_state {
|
struct _dtoa_state {
|
||||||
int _not_used;
|
int _not_used;
|
||||||
};
|
};
|
||||||
#define _dtoa_runtime_state_INIT {0}
|
#define _dtoa_interp_state_INIT(INTERP) \
|
||||||
|
{0}
|
||||||
|
|
||||||
#else // !Py_USING_MEMORY_DEBUGGER
|
#else // !Py_USING_MEMORY_DEBUGGER
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ struct _dtoa_runtime_state {
|
||||||
#define Bigint_PREALLOC_SIZE \
|
#define Bigint_PREALLOC_SIZE \
|
||||||
((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
|
((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 */
|
/* 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.
|
// XXX This should be freed during runtime fini.
|
||||||
struct Bigint *p5s;
|
struct Bigint *p5s;
|
||||||
|
@ -48,9 +49,9 @@ struct _dtoa_runtime_state {
|
||||||
double preallocated[Bigint_PREALLOC_SIZE];
|
double preallocated[Bigint_PREALLOC_SIZE];
|
||||||
double *preallocated_next;
|
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
|
#endif // !Py_USING_MEMORY_DEBUGGER
|
||||||
|
|
|
@ -16,6 +16,7 @@ extern "C" {
|
||||||
#include "pycore_code.h" // struct callable_cache
|
#include "pycore_code.h" // struct callable_cache
|
||||||
#include "pycore_context.h" // struct _Py_context_state
|
#include "pycore_context.h" // struct _Py_context_state
|
||||||
#include "pycore_dict_state.h" // struct _Py_dict_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_exceptions.h" // struct _Py_exc_state
|
||||||
#include "pycore_floatobject.h" // struct _Py_float_state
|
#include "pycore_floatobject.h" // struct _Py_float_state
|
||||||
#include "pycore_function.h" // FUNC_MAX_WATCHERS
|
#include "pycore_function.h" // FUNC_MAX_WATCHERS
|
||||||
|
@ -139,6 +140,7 @@ struct _is {
|
||||||
struct _Py_unicode_state unicode;
|
struct _Py_unicode_state unicode;
|
||||||
struct _Py_float_state float_state;
|
struct _Py_float_state float_state;
|
||||||
struct _Py_long_state long_state;
|
struct _Py_long_state long_state;
|
||||||
|
struct _dtoa_state dtoa;
|
||||||
/* Using a cache is very effective since typically only a single slice is
|
/* Using a cache is very effective since typically only a single slice is
|
||||||
created and then deleted again. */
|
created and then deleted again. */
|
||||||
PySliceObject *slice_cache;
|
PySliceObject *slice_cache;
|
||||||
|
|
|
@ -11,7 +11,6 @@ extern "C" {
|
||||||
#include "pycore_atomic.h" /* _Py_atomic_address */
|
#include "pycore_atomic.h" /* _Py_atomic_address */
|
||||||
#include "pycore_ceval_state.h" // struct _ceval_runtime_state
|
#include "pycore_ceval_state.h" // struct _ceval_runtime_state
|
||||||
#include "pycore_dict_state.h" // struct _Py_dict_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_floatobject.h" // struct _Py_float_runtime_state
|
||||||
#include "pycore_faulthandler.h" // struct _faulthandler_runtime_state
|
#include "pycore_faulthandler.h" // struct _faulthandler_runtime_state
|
||||||
#include "pycore_function.h" // struct _func_runtime_state
|
#include "pycore_function.h" // struct _func_runtime_state
|
||||||
|
@ -141,7 +140,6 @@ typedef struct pyruntimestate {
|
||||||
struct _ceval_runtime_state ceval;
|
struct _ceval_runtime_state ceval;
|
||||||
struct _gilstate_runtime_state gilstate;
|
struct _gilstate_runtime_state gilstate;
|
||||||
struct _getargs_runtime_state getargs;
|
struct _getargs_runtime_state getargs;
|
||||||
struct _dtoa_runtime_state dtoa;
|
|
||||||
struct _fileutils_state fileutils;
|
struct _fileutils_state fileutils;
|
||||||
struct _faulthandler_runtime_state faulthandler;
|
struct _faulthandler_runtime_state faulthandler;
|
||||||
struct _tracemalloc_runtime_state tracemalloc;
|
struct _tracemalloc_runtime_state tracemalloc;
|
||||||
|
|
|
@ -53,7 +53,6 @@ extern "C" {
|
||||||
.gilstate = { \
|
.gilstate = { \
|
||||||
.check_enabled = 1, \
|
.check_enabled = 1, \
|
||||||
}, \
|
}, \
|
||||||
.dtoa = _dtoa_runtime_state_INIT(runtime), \
|
|
||||||
.fileutils = { \
|
.fileutils = { \
|
||||||
.force_ascii = -1, \
|
.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, \
|
.id_refcount = -1, \
|
||||||
.imports = IMPORTS_INIT, \
|
.imports = IMPORTS_INIT, \
|
||||||
|
@ -113,6 +112,7 @@ extern "C" {
|
||||||
{ .threshold = 10, }, \
|
{ .threshold = 10, }, \
|
||||||
}, \
|
}, \
|
||||||
}, \
|
}, \
|
||||||
|
.dtoa = _dtoa_state_INIT(&(INTERP)), \
|
||||||
.static_objects = { \
|
.static_objects = { \
|
||||||
.singletons = { \
|
.singletons = { \
|
||||||
._not_used = 1, \
|
._not_used = 1, \
|
||||||
|
|
|
@ -119,7 +119,7 @@
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_dtoa.h" // _PY_SHORT_FLOAT_REPR
|
#include "pycore_dtoa.h" // _PY_SHORT_FLOAT_REPR
|
||||||
#include "pycore_runtime.h" // _PyRuntime
|
#include "pycore_pystate.h" // _PyInterpreterState_GET()
|
||||||
#include <stdlib.h> // exit()
|
#include <stdlib.h> // exit()
|
||||||
|
|
||||||
/* if _PY_SHORT_FLOAT_REPR == 0, then don't even try to compile
|
/* 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
|
Bfree to PyMem_Free. Investigate whether this has any significant
|
||||||
performance on impact. */
|
performance on impact. */
|
||||||
|
|
||||||
#define freelist _PyRuntime.dtoa.freelist
|
#define freelist interp->dtoa.freelist
|
||||||
#define private_mem _PyRuntime.dtoa.preallocated
|
#define private_mem interp->dtoa.preallocated
|
||||||
#define pmem_next _PyRuntime.dtoa.preallocated_next
|
#define pmem_next interp->dtoa.preallocated_next
|
||||||
|
|
||||||
/* Allocate space for a Bigint with up to 1<<k digits */
|
/* Allocate space for a Bigint with up to 1<<k digits */
|
||||||
|
|
||||||
|
@ -351,6 +351,7 @@ Balloc(int k)
|
||||||
int x;
|
int x;
|
||||||
Bigint *rv;
|
Bigint *rv;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
|
||||||
if (k <= Bigint_Kmax && (rv = freelist[k]))
|
if (k <= Bigint_Kmax && (rv = freelist[k]))
|
||||||
freelist[k] = rv->next;
|
freelist[k] = rv->next;
|
||||||
|
@ -385,6 +386,7 @@ Bfree(Bigint *v)
|
||||||
if (v->k > Bigint_Kmax)
|
if (v->k > Bigint_Kmax)
|
||||||
FREE((void*)v);
|
FREE((void*)v);
|
||||||
else {
|
else {
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
v->next = freelist[v->k];
|
v->next = freelist[v->k];
|
||||||
freelist[v->k] = v;
|
freelist[v->k] = v;
|
||||||
}
|
}
|
||||||
|
@ -692,7 +694,8 @@ pow5mult(Bigint *b, int k)
|
||||||
|
|
||||||
if (!(k >>= 2))
|
if (!(k >>= 2))
|
||||||
return b;
|
return b;
|
||||||
p5 = _PyRuntime.dtoa.p5s;
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
p5 = interp->dtoa.p5s;
|
||||||
if (!p5) {
|
if (!p5) {
|
||||||
/* first time */
|
/* first time */
|
||||||
p5 = i2b(625);
|
p5 = i2b(625);
|
||||||
|
@ -700,7 +703,7 @@ pow5mult(Bigint *b, int k)
|
||||||
Bfree(b);
|
Bfree(b);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
_PyRuntime.dtoa.p5s = p5;
|
interp->dtoa.p5s = p5;
|
||||||
p5->next = 0;
|
p5->next = 0;
|
||||||
}
|
}
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_ceval.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_frame.h"
|
||||||
#include "pycore_initconfig.h"
|
#include "pycore_initconfig.h"
|
||||||
#include "pycore_object.h" // _PyType_InitCache()
|
#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.
|
e.g. by PyMem_RawCalloc() or memset(), or otherwise pre-initialized.
|
||||||
The runtime state is not manipulated. Instead it is assumed that
|
The runtime state is not manipulated. Instead it is assumed that
|
||||||
the interpreter is getting added to the runtime.
|
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
|
static void
|
||||||
|
@ -645,6 +658,11 @@ init_interpreter(PyInterpreterState *interp,
|
||||||
PyConfig_InitPythonConfig(&interp->config);
|
PyConfig_InitPythonConfig(&interp->config);
|
||||||
_PyType_InitCache(interp);
|
_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;
|
interp->_initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue