mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +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
	
	 Eric Snow
						Eric Snow