#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
#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;
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
#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
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;
#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
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;
.gilstate = { \
.check_enabled = 1, \
}, \
- .dtoa = _dtoa_runtime_state_INIT(runtime), \
.fileutils = { \
.force_ascii = -1, \
}, \
}, \
}, \
}, \
- ._main_interpreter = _PyInterpreterState_INIT, \
+ ._main_interpreter = _PyInterpreterState_INIT(runtime._main_interpreter), \
}
-#define _PyInterpreterState_INIT \
+#define _PyInterpreterState_INIT(INTERP) \
{ \
.id_refcount = -1, \
.imports = IMPORTS_INIT, \
{ .threshold = 10, }, \
}, \
}, \
+ .dtoa = _dtoa_state_INIT(&(INTERP)), \
.static_objects = { \
.singletons = { \
._not_used = 1, \
#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
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 */
int x;
Bigint *rv;
unsigned int len;
+ PyInterpreterState *interp = _PyInterpreterState_GET();
if (k <= Bigint_Kmax && (rv = freelist[k]))
freelist[k] = rv->next;
if (v->k > Bigint_Kmax)
FREE((void*)v);
else {
+ PyInterpreterState *interp = _PyInterpreterState_GET();
v->next = freelist[v->k];
freelist[v->k] = v;
}
if (!(k >>= 2))
return b;
- p5 = _PyRuntime.dtoa.p5s;
+ PyInterpreterState *interp = _PyInterpreterState_GET();
+ p5 = interp->dtoa.p5s;
if (!p5) {
/* first time */
p5 = i2b(625);
Bfree(b);
return NULL;
}
- _PyRuntime.dtoa.p5s = p5;
+ interp->dtoa.p5s = p5;
p5->next = 0;
}
for(;;) {
#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()
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
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;
}