Skip to content

Commit

Permalink
pythongh-100227: Move the dtoa State to PyInterpreterState (pythongh-…
Browse files Browse the repository at this point in the history
  • Loading branch information
ericsnowcurrently authored Feb 28, 2023
1 parent b5ff382 commit f300a1f
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 17 deletions.
11 changes: 6 additions & 5 deletions Include/internal/pycore_dtoa.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -40,17 +41,17 @@ 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;
struct Bigint *freelist[Bigint_Kmax+1];
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
Expand Down
2 changes: 2 additions & 0 deletions Include/internal/pycore_interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 0 additions & 2 deletions Include/internal/pycore_runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions Include/internal/pycore_runtime_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ extern "C" {
.gilstate = { \
.check_enabled = 1, \
}, \
.dtoa = _dtoa_runtime_state_INIT(runtime), \
.fileutils = { \
.force_ascii = -1, \
}, \
Expand Down Expand Up @@ -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, \
Expand All @@ -113,6 +112,7 @@ extern "C" {
{ .threshold = 10, }, \
}, \
}, \
.dtoa = _dtoa_state_INIT(&(INTERP)), \
.static_objects = { \
.singletons = { \
._not_used = 1, \
Expand Down
15 changes: 9 additions & 6 deletions Python/dtoa.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */

Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -692,15 +694,16 @@ 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);
if (p5 == NULL) {
Bfree(b);
return NULL;
}
_PyRuntime.dtoa.p5s = p5;
interp->dtoa.p5s = p5;
p5->next = 0;
}
for(;;) {
Expand Down
20 changes: 19 additions & 1 deletion Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit f300a1f

Please sign in to comment.