diff options
Diffstat (limited to 'Include')
-rw-r--r-- | Include/internal/pycore_bytesobject.h | 30 | ||||
-rw-r--r-- | Include/internal/pycore_context.h | 29 | ||||
-rw-r--r-- | Include/internal/pycore_dict.h | 26 | ||||
-rw-r--r-- | Include/internal/pycore_exceptions.h | 37 | ||||
-rw-r--r-- | Include/internal/pycore_floatobject.h | 29 | ||||
-rw-r--r-- | Include/internal/pycore_frame.h | 8 | ||||
-rw-r--r-- | Include/internal/pycore_genobject.h | 46 | ||||
-rw-r--r-- | Include/internal/pycore_hamt.h | 11 | ||||
-rw-r--r-- | Include/internal/pycore_interp.h | 183 | ||||
-rw-r--r-- | Include/internal/pycore_list.h | 24 | ||||
-rw-r--r-- | Include/internal/pycore_long.h | 16 | ||||
-rw-r--r-- | Include/internal/pycore_long_state.h | 33 | ||||
-rw-r--r-- | Include/internal/pycore_pyerrors.h | 8 | ||||
-rw-r--r-- | Include/internal/pycore_pylifecycle.h | 28 | ||||
-rw-r--r-- | Include/internal/pycore_runtime.h | 24 | ||||
-rw-r--r-- | Include/internal/pycore_sliceobject.h | 20 | ||||
-rw-r--r-- | Include/internal/pycore_structseq.h | 7 | ||||
-rw-r--r-- | Include/internal/pycore_tuple.h | 37 | ||||
-rw-r--r-- | Include/internal/pycore_typeobject.h | 47 | ||||
-rw-r--r-- | Include/internal/pycore_unicodeobject.h | 71 |
20 files changed, 483 insertions, 231 deletions
diff --git a/Include/internal/pycore_bytesobject.h b/Include/internal/pycore_bytesobject.h new file mode 100644 index 0000000000..b00ed9784e --- /dev/null +++ b/Include/internal/pycore_bytesobject.h @@ -0,0 +1,30 @@ +#ifndef Py_INTERNAL_BYTESOBJECT_H +#define Py_INTERNAL_BYTESOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +/* runtime lifecycle */ + +extern PyStatus _PyBytes_InitGlobalObjects(PyInterpreterState *); +extern PyStatus _PyBytes_InitTypes(PyInterpreterState *); +extern void _PyBytes_Fini(PyInterpreterState *); + + +/* other API */ + +struct _Py_bytes_state { + PyObject *empty_string; + PyBytesObject *characters[256]; +}; + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_BYTESOBJECT_H */ diff --git a/Include/internal/pycore_context.h b/Include/internal/pycore_context.h index a482dd4212..31ca0a43fa 100644 --- a/Include/internal/pycore_context.h +++ b/Include/internal/pycore_context.h @@ -7,6 +7,32 @@ #include "pycore_hamt.h" /* PyHamtObject */ + +/* runtime lifecycle */ + +PyStatus _PyContext_InitTypes(PyInterpreterState *); +void _PyContext_Fini(PyInterpreterState *); + + +/* other API */ + +#ifndef WITH_FREELISTS +// without freelists +# define PyContext_MAXFREELIST 0 +#endif + +#ifndef PyContext_MAXFREELIST +# define PyContext_MAXFREELIST 255 +#endif + +struct _Py_context_state { +#if PyContext_MAXFREELIST > 0 + // List of free PyContext objects + PyContext *freelist; + int numfree; +#endif +}; + struct _pycontextobject { PyObject_HEAD PyContext *ctx_prev; @@ -36,7 +62,4 @@ struct _pycontexttokenobject { }; -int _PyContext_Init(void); -void _PyContext_Fini(PyInterpreterState *interp); - #endif /* !Py_INTERNAL_CONTEXT_H */ diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index 2f0536801e..faa8bb49bb 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -10,6 +10,32 @@ extern "C" { #endif +/* runtime lifecycle */ + +extern void _PyDict_Fini(PyInterpreterState *interp); + + +/* other API */ + +#ifndef WITH_FREELISTS +// without freelists +# define PyDict_MAXFREELIST 0 +#endif + +#ifndef PyDict_MAXFREELIST +# define PyDict_MAXFREELIST 80 +#endif + +struct _Py_dict_state { +#if PyDict_MAXFREELIST > 0 + /* Dictionary reuse scheme to save calls to malloc and free */ + PyDictObject *free_list[PyDict_MAXFREELIST]; + int numfree; + PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST]; + int keys_numfree; +#endif +}; + typedef struct { /* Cached hash code of me_key. */ Py_hash_t me_hash; diff --git a/Include/internal/pycore_exceptions.h b/Include/internal/pycore_exceptions.h new file mode 100644 index 0000000000..1651966dad --- /dev/null +++ b/Include/internal/pycore_exceptions.h @@ -0,0 +1,37 @@ +#ifndef Py_INTERNAL_EXCEPTIONS_H +#define Py_INTERNAL_EXCEPTIONS_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +/* runtime lifecycle */ + +extern PyStatus _PyExc_InitState(PyInterpreterState *); +extern PyStatus _PyExc_InitGlobalObjects(PyInterpreterState *); +extern PyStatus _PyExc_InitTypes(PyInterpreterState *); +extern void _PyExc_Fini(PyInterpreterState *); + + +/* other API */ + +struct _Py_exc_state { + // The dict mapping from errno codes to OSError subclasses + PyObject *errnomap; + PyBaseExceptionObject *memerrors_freelist; + int memerrors_numfree; + // The ExceptionGroup type + PyObject *PyExc_ExceptionGroup; +}; + +extern void _PyExc_ClearExceptionGroupType(PyInterpreterState *); + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_EXCEPTIONS_H */ diff --git a/Include/internal/pycore_floatobject.h b/Include/internal/pycore_floatobject.h index 18227c9e36..be6045587d 100644 --- a/Include/internal/pycore_floatobject.h +++ b/Include/internal/pycore_floatobject.h @@ -8,6 +8,35 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif + +/* runtime lifecycle */ + +extern void _PyFloat_InitState(PyInterpreterState *); +extern PyStatus _PyFloat_InitTypes(PyInterpreterState *); +extern void _PyFloat_Fini(PyInterpreterState *); + + +/* other API */ + +#ifndef WITH_FREELISTS +// without freelists +# define PyFloat_MAXFREELIST 0 +#endif + +#ifndef PyFloat_MAXFREELIST +# define PyFloat_MAXFREELIST 100 +#endif + +struct _Py_float_state { +#if PyFloat_MAXFREELIST > 0 + /* Special free list + free_list is a singly-linked list of available PyFloatObjects, + linked via abuse of their ob_type members. */ + int numfree; + PyFloatObject *free_list; +#endif +}; + /* _PyFloat_{Pack,Unpack}{4,8} * * The struct and pickle (at least) modules need an efficient platform- diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index f4f7ab942c..a55877b55f 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -4,6 +4,14 @@ extern "C" { #endif + +/* runtime lifecycle */ + +extern void _PyFrame_Fini(PyInterpreterState *interp); + + +/* other API */ + /* These values are chosen so that the inline functions below all * compare f_state to zero. */ diff --git a/Include/internal/pycore_genobject.h b/Include/internal/pycore_genobject.h new file mode 100644 index 0000000000..74a676df4a --- /dev/null +++ b/Include/internal/pycore_genobject.h @@ -0,0 +1,46 @@ +#ifndef Py_INTERNAL_GENOBJECT_H +#define Py_INTERNAL_GENOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +/* runtime lifecycle */ + +extern void _PyAsyncGen_Fini(PyInterpreterState *); + + +/* other API */ + +#ifndef WITH_FREELISTS +// without freelists +# define _PyAsyncGen_MAXFREELIST 0 +#endif + +#ifndef _PyAsyncGen_MAXFREELIST +# define _PyAsyncGen_MAXFREELIST 80 +#endif + +struct _Py_async_gen_state { +#if _PyAsyncGen_MAXFREELIST > 0 + /* Freelists boost performance 6-10%; they also reduce memory + fragmentation, as _PyAsyncGenWrappedValue and PyAsyncGenASend + are short-living objects that are instantiated for every + __anext__() call. */ + struct _PyAsyncGenWrappedValue* value_freelist[_PyAsyncGen_MAXFREELIST]; + int value_numfree; + + struct PyAsyncGenASend* asend_freelist[_PyAsyncGen_MAXFREELIST]; + int asend_numfree; +#endif +}; + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_GENOBJECT_H */ diff --git a/Include/internal/pycore_hamt.h b/Include/internal/pycore_hamt.h index aaf6559095..cf9c19e022 100644 --- a/Include/internal/pycore_hamt.h +++ b/Include/internal/pycore_hamt.h @@ -8,6 +8,14 @@ #define _Py_HAMT_MAX_TREE_DEPTH 7 +/* runtime lifecycle */ + +PyStatus _PyHamt_InitTypes(PyInterpreterState *); +void _PyHamt_Fini(PyInterpreterState *); + + +/* other API */ + #define PyHamt_Check(o) Py_IS_TYPE(o, &_PyHamt_Type) @@ -110,7 +118,4 @@ PyObject * _PyHamt_NewIterValues(PyHamtObject *o); /* Return a Items iterator over "o". */ PyObject * _PyHamt_NewIterItems(PyHamtObject *o); -int _PyHamt_Init(void); -void _PyHamt_Fini(void); - #endif /* !Py_INTERNAL_HAMT_H */ diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index e421aa4bc4..e4d7b1b875 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -10,8 +10,18 @@ extern "C" { #include "pycore_atomic.h" // _Py_atomic_address #include "pycore_ast_state.h" // struct ast_state +#include "pycore_bytesobject.h" // struct _Py_bytes_state +#include "pycore_context.h" // struct _Py_context_state +#include "pycore_dict.h" // struct _Py_dict_state +#include "pycore_exceptions.h" // struct _Py_exc_state +#include "pycore_floatobject.h" // struct _Py_float_state +#include "pycore_genobject.h" // struct _Py_async_gen_state #include "pycore_gil.h" // struct _gil_runtime_state #include "pycore_gc.h" // struct _gc_runtime_state +#include "pycore_list.h" // struct _Py_list_state +#include "pycore_tuple.h" // struct _Py_tuple_state +#include "pycore_typeobject.h" // struct type_cache +#include "pycore_unicodeobject.h" // struct _Py_unicode_state #include "pycore_warnings.h" // struct _warnings_runtime_state struct _pending_calls { @@ -44,158 +54,6 @@ struct _ceval_state { #endif }; -/* fs_codec.encoding is initialized to NULL. - Later, it is set to a non-NULL string by _PyUnicode_InitEncodings(). */ -struct _Py_unicode_fs_codec { - char *encoding; // Filesystem encoding (encoded to UTF-8) - int utf8; // encoding=="utf-8"? - char *errors; // Filesystem errors (encoded to UTF-8) - _Py_error_handler error_handler; -}; - -struct _Py_bytes_state { - PyObject *empty_string; - PyBytesObject *characters[256]; -}; - -struct _Py_unicode_ids { - Py_ssize_t size; - PyObject **array; -}; - -struct _Py_unicode_state { - // The empty Unicode object is a singleton to improve performance. - PyObject *empty_string; - /* Single character Unicode strings in the Latin-1 range are being - shared as well. */ - PyObject *latin1[256]; - struct _Py_unicode_fs_codec fs_codec; - - /* This dictionary holds all interned unicode strings. Note that references - to strings in this dictionary are *not* counted in the string's ob_refcnt. - When the interned string reaches a refcnt of 0 the string deallocation - function will delete the reference from this dictionary. - - Another way to look at this is that to say that the actual reference - count of a string is: s->ob_refcnt + (s->state ? 2 : 0) - */ - PyObject *interned; - - // Unicode identifiers (_Py_Identifier): see _PyUnicode_FromId() - struct _Py_unicode_ids ids; -}; - -#ifndef WITH_FREELISTS -// without freelists -# define PyFloat_MAXFREELIST 0 -// for tuples only store empty tuple singleton -# define PyTuple_MAXSAVESIZE 1 -# define PyTuple_MAXFREELIST 1 -# define PyList_MAXFREELIST 0 -# define PyDict_MAXFREELIST 0 -# define _PyAsyncGen_MAXFREELIST 0 -# define PyContext_MAXFREELIST 0 -#endif - -#ifndef PyFloat_MAXFREELIST -# define PyFloat_MAXFREELIST 100 -#endif - -struct _Py_float_state { -#if PyFloat_MAXFREELIST > 0 - /* Special free list - free_list is a singly-linked list of available PyFloatObjects, - linked via abuse of their ob_type members. */ - int numfree; - PyFloatObject *free_list; -#endif -}; - -/* Speed optimization to avoid frequent malloc/free of small tuples */ -#ifndef PyTuple_MAXSAVESIZE - // Largest tuple to save on free list -# define PyTuple_MAXSAVESIZE 20 -#endif -#ifndef PyTuple_MAXFREELIST - // Maximum number of tuples of each size to save -# define PyTuple_MAXFREELIST 2000 -#endif - -struct _Py_tuple_state { -#if PyTuple_MAXSAVESIZE > 0 - /* Entries 1 up to PyTuple_MAXSAVESIZE are free lists, - entry 0 is the empty tuple () of which at most one instance - will be allocated. */ - PyTupleObject *free_list[PyTuple_MAXSAVESIZE]; - int numfree[PyTuple_MAXSAVESIZE]; -#endif -}; - -/* Empty list reuse scheme to save calls to malloc and free */ -#ifndef PyList_MAXFREELIST -# define PyList_MAXFREELIST 80 -#endif - -struct _Py_list_state { -#if PyList_MAXFREELIST > 0 - PyListObject *free_list[PyList_MAXFREELIST]; - int numfree; -#endif -}; - -#ifndef PyDict_MAXFREELIST -# define PyDict_MAXFREELIST 80 -#endif - -struct _Py_dict_state { -#if PyDict_MAXFREELIST > 0 - /* Dictionary reuse scheme to save calls to malloc and free */ - PyDictObject *free_list[PyDict_MAXFREELIST]; - int numfree; - PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST]; - int keys_numfree; -#endif -}; - -#ifndef _PyAsyncGen_MAXFREELIST -# define _PyAsyncGen_MAXFREELIST 80 -#endif - -struct _Py_async_gen_state { -#if _PyAsyncGen_MAXFREELIST > 0 - /* Freelists boost performance 6-10%; they also reduce memory - fragmentation, as _PyAsyncGenWrappedValue and PyAsyncGenASend - are short-living objects that are instantiated for every - __anext__() call. */ - struct _PyAsyncGenWrappedValue* value_freelist[_PyAsyncGen_MAXFREELIST]; - int value_numfree; - - struct PyAsyncGenASend* asend_freelist[_PyAsyncGen_MAXFREELIST]; - int asend_numfree; -#endif -}; - -#ifndef PyContext_MAXFREELIST -# define PyContext_MAXFREELIST 255 -#endif - -struct _Py_context_state { -#if PyContext_MAXFREELIST > 0 - // List of free PyContext objects - PyContext *freelist; - int numfree; -#endif -}; - -struct _Py_exc_state { - // The dict mapping from errno codes to OSError subclasses - PyObject *errnomap; - PyBaseExceptionObject *memerrors_freelist; - int memerrors_numfree; - // The ExceptionGroup type - PyObject *PyExc_ExceptionGroup; -}; - // atexit state typedef struct { @@ -211,27 +69,6 @@ struct atexit_state { }; -// Type attribute lookup cache: speed up attribute and method lookups, -// see _PyType_Lookup(). -struct type_cache_entry { - unsigned int version; // initialized from type->tp_version_tag - PyObject *name; // reference to exactly a str or None - PyObject *value; // borrowed reference or NULL -}; - -#define MCACHE_SIZE_EXP 12 -#define MCACHE_STATS 0 - -struct type_cache { - struct type_cache_entry hashtable[1 << MCACHE_SIZE_EXP]; -#if MCACHE_STATS - size_t hits; - size_t misses; - size_t collisions; -#endif -}; - - /* interpreter state */ // The PyInterpreterState typedef is in Include/pystate.h. diff --git a/Include/internal/pycore_list.h b/Include/internal/pycore_list.h index f18fb052c4..0717a1f956 100644 --- a/Include/internal/pycore_list.h +++ b/Include/internal/pycore_list.h @@ -11,6 +11,30 @@ extern "C" { #include "listobject.h" // _PyList_CAST() +/* runtime lifecycle */ + +extern void _PyList_Fini(PyInterpreterState *); + + +/* other API */ + +#ifndef WITH_FREELISTS +// without freelists +# define PyList_MAXFREELIST 0 +#endif + +/* Empty list reuse scheme to save calls to malloc and free */ +#ifndef PyList_MAXFREELIST +# define PyList_MAXFREELIST 80 +#endif + +struct _Py_list_state { +#if PyList_MAXFREELIST > 0 + PyListObject *free_list[PyList_MAXFREELIST]; + int numfree; +#endif +}; + #define _PyList_ITEMS(op) (_PyList_CAST(op)->ob_item) diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index b9f926996d..a5639ceb69 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -8,18 +8,28 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_interp.h" // PyInterpreterState.small_ints +#include "pycore_long_state.h" // _PyLong_SMALL_INTS #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_runtime.h" // _PyRuntime + + +/* runtime lifecycle */ + +extern void _PyLong_InitGlobalObjects(PyInterpreterState *); +extern PyStatus _PyLong_InitTypes(PyInterpreterState *); + + +/* other API */ // Return a borrowed reference to the zero singleton. // The function cannot return NULL. static inline PyObject* _PyLong_GetZero(void) -{ return (PyObject *)&_PyRuntime.small_ints[_PY_NSMALLNEGINTS]; } +{ return (PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS]; } // Return a borrowed reference to the one singleton. // The function cannot return NULL. static inline PyObject* _PyLong_GetOne(void) -{ return (PyObject *)&_PyRuntime.small_ints[_PY_NSMALLNEGINTS+1]; } +{ return (PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+1]; } PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right); PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right); diff --git a/Include/internal/pycore_long_state.h b/Include/internal/pycore_long_state.h new file mode 100644 index 0000000000..5fe8e623a9 --- /dev/null +++ b/Include/internal/pycore_long_state.h @@ -0,0 +1,33 @@ +#ifndef Py_INTERNAL_LONG_STATE_H +#define Py_INTERNAL_LONG_STATE_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#define _PY_NSMALLPOSINTS 257 +#define _PY_NSMALLNEGINTS 5 + +// _PyLong_GetZero() and _PyLong_GetOne() must always be available +#if _PY_NSMALLPOSINTS < 2 +# error "_PY_NSMALLPOSINTS must be greater than 1" +#endif + +struct _Py_long_state { + /* Small integers are preallocated in this array so that they + * can be shared. + * The integers that are preallocated are those in the range + *-_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (not inclusive). + */ + PyLongObject small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS]; +}; + +#define _PyLong_SMALL_INTS _PyRuntime.int_state.small_ints + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_LONG_STATE_H */ diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index 14ea182f4f..3134afeb86 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -8,6 +8,14 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif + +/* runtime lifecycle */ + +extern PyStatus _PyErr_InitTypes(PyInterpreterState *); + + +/* other API */ + static inline PyObject* _PyErr_Occurred(PyThreadState *tstate) { assert(tstate != NULL); diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 5e0f36ab2a..766e889f23 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -49,13 +49,6 @@ PyAPI_FUNC(int) _Py_IsLocaleCoercionTarget(const char *ctype_loc); /* Various one-time initializers */ -extern PyStatus _PyUnicode_Init(PyInterpreterState *interp); -extern PyStatus _PyUnicode_InitTypes(void); -extern PyStatus _PyBytes_Init(PyInterpreterState *interp); -extern int _PyStructSequence_Init(void); -extern void _PyLong_Init(PyInterpreterState *interp); -extern int _PyLong_InitTypes(void); -extern PyStatus _PyTuple_Init(PyInterpreterState *interp); extern PyStatus _PyFaulthandler_Init(int enable); extern int _PyTraceMalloc_Init(int enable); extern PyObject * _PyBuiltin_Init(PyInterpreterState *interp); @@ -65,15 +58,9 @@ extern PyStatus _PySys_Create( extern PyStatus _PySys_ReadPreinitWarnOptions(PyWideStringList *options); extern PyStatus _PySys_ReadPreinitXOptions(PyConfig *config); extern int _PySys_UpdateConfig(PyThreadState *tstate); -extern PyStatus _PyExc_Init(PyInterpreterState *interp); -extern PyStatus _PyErr_InitTypes(void); extern PyStatus _PyBuiltins_AddExceptions(PyObject * bltinmod); -extern void _PyFloat_Init(void); -extern int _PyFloat_InitTypes(void); extern PyStatus _Py_HashRandomization_Init(const PyConfig *); -extern PyStatus _PyTypes_Init(void); -extern PyStatus _PyTypes_InitSlotDefs(void); extern PyStatus _PyImportZip_Init(PyThreadState *tstate); extern PyStatus _PyGC_Init(PyInterpreterState *interp); extern PyStatus _PyAtExit_Init(PyInterpreterState *interp); @@ -81,28 +68,13 @@ extern PyStatus _PyAtExit_Init(PyInterpreterState *interp); /* Various internal finalizers */ -extern void _PyFrame_Fini(PyInterpreterState *interp); -extern void _PyDict_Fini(PyInterpreterState *interp); -extern void _PyTuple_Fini(PyInterpreterState *interp); -extern void _PyList_Fini(PyInterpreterState *interp); -extern void _PyBytes_Fini(PyInterpreterState *interp); -extern void _PyFloat_Fini(PyInterpreterState *interp); -extern void _PySlice_Fini(PyInterpreterState *interp); -extern void _PyAsyncGen_Fini(PyInterpreterState *interp); - extern int _PySignal_Init(int install_signal_handlers); extern void _PySignal_Fini(void); -extern void _PyExc_ClearExceptionGroupType(PyInterpreterState *interp); -extern void _PyExc_Fini(PyInterpreterState *interp); extern void _PyImport_Fini(void); extern void _PyImport_Fini2(void); extern void _PyGC_Fini(PyInterpreterState *interp); -extern void _PyType_Fini(PyInterpreterState *interp); extern void _Py_HashRandomization_Fini(void); -extern void _PyUnicode_Fini(PyInterpreterState *interp); -extern void _PyUnicode_ClearInterned(PyInterpreterState *interp); -extern void _PyLong_Fini(PyInterpreterState *interp); extern void _PyFaulthandler_Fini(void); extern void _PyHash_Fini(void); extern void _PyTraceMalloc_Fini(void); diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h index 39e30b785a..bd88510d1f 100644 --- a/Include/internal/pycore_runtime.h +++ b/Include/internal/pycore_runtime.h @@ -10,14 +10,8 @@ extern "C" { #include "pycore_atomic.h" /* _Py_atomic_address */ #include "pycore_gil.h" // struct _gil_runtime_state - -#define _PY_NSMALLPOSINTS 257 -#define _PY_NSMALLNEGINTS 5 - -// _PyLong_GetZero() and _PyLong_GetOne() must always be available -#if _PY_NSMALLPOSINTS < 2 -# error "_PY_NSMALLPOSINTS must be greater than 1" -#endif +#include "pycore_long_state.h" // struct _Py_long_state +#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids /* ceval state */ @@ -57,13 +51,6 @@ typedef struct _Py_AuditHookEntry { void *userData; } _Py_AuditHookEntry; -struct _Py_unicode_runtime_ids { - PyThread_type_lock lock; - // next_index value must be preserved when Py_Initialize()/Py_Finalize() - // is called multiple times: see _PyUnicode_FromId() implementation. - Py_ssize_t next_index; -}; - /* Full Python runtime state */ typedef struct pyruntimestate { @@ -114,12 +101,7 @@ typedef struct pyruntimestate { unsigned long main_thread; - /* Small integers are preallocated in this array so that they - * can be shared. - * The integers that are preallocated are those in the range - *-_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (not inclusive). - */ - PyLongObject small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS]; + struct _Py_long_state int_state; #define NEXITFUNCS 32 void (*exitfuncs[NEXITFUNCS])(void); diff --git a/Include/internal/pycore_sliceobject.h b/Include/internal/pycore_sliceobject.h new file mode 100644 index 0000000000..e81834c041 --- /dev/null +++ b/Include/internal/pycore_sliceobject.h @@ -0,0 +1,20 @@ +#ifndef Py_INTERNAL_SLICEOBJECT_H +#define Py_INTERNAL_SLICEOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +/* runtime lifecycle */ + +extern void _PySlice_Fini(PyInterpreterState *); + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_SLICEOBJECT_H */ diff --git a/Include/internal/pycore_structseq.h b/Include/internal/pycore_structseq.h index 84c8d477e0..3a61cb9a12 100644 --- a/Include/internal/pycore_structseq.h +++ b/Include/internal/pycore_structseq.h @@ -9,6 +9,13 @@ extern "C" { #endif +/* runtime lifecycle */ + +extern PyStatus _PyStructSequence_InitState(PyInterpreterState *); + + +/* other API */ + PyAPI_FUNC(int) _PyStructSequence_InitType( PyTypeObject *type, PyStructSequence_Desc *desc, diff --git a/Include/internal/pycore_tuple.h b/Include/internal/pycore_tuple.h index 79c827fe88..624c21caec 100644 --- a/Include/internal/pycore_tuple.h +++ b/Include/internal/pycore_tuple.h @@ -10,6 +10,43 @@ extern "C" { #include "tupleobject.h" /* _PyTuple_CAST() */ + +/* runtime lifecycle */ + +extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *); +extern PyStatus _PyTuple_InitTypes(PyInterpreterState *); +extern void _PyTuple_Fini(PyInterpreterState *); + + +/* other API */ + +#ifndef WITH_FREELISTS +// without freelists +// for tuples only store empty tuple singleton +# define PyTuple_MAXSAVESIZE 1 +# define PyTuple_MAXFREELIST 1 +#endif + +/* Speed optimization to avoid frequent malloc/free of small tuples */ +#ifndef PyTuple_MAXSAVESIZE + // Largest tuple to save on free list +# define PyTuple_MAXSAVESIZE 20 +#endif +#ifndef PyTuple_MAXFREELIST + // Maximum number of tuples of each size to save +# define PyTuple_MAXFREELIST 2000 +#endif + +struct _Py_tuple_state { +#if PyTuple_MAXSAVESIZE > 0 + /* Entries 1 up to PyTuple_MAXSAVESIZE are free lists, + entry 0 is the empty tuple () of which at most one instance + will be allocated. */ + PyTupleObject *free_list[PyTuple_MAXSAVESIZE]; + int numfree[PyTuple_MAXSAVESIZE]; +#endif +}; + #define _PyTuple_ITEMS(op) (_PyTuple_CAST(op)->ob_item) extern PyObject *_PyTuple_FromArray(PyObject *const *, Py_ssize_t); diff --git a/Include/internal/pycore_typeobject.h b/Include/internal/pycore_typeobject.h new file mode 100644 index 0000000000..7fd8a1f350 --- /dev/null +++ b/Include/internal/pycore_typeobject.h @@ -0,0 +1,47 @@ +#ifndef Py_INTERNAL_TYPEOBJECT_H +#define Py_INTERNAL_TYPEOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +/* runtime lifecycle */ + +extern PyStatus _PyTypes_InitState(PyInterpreterState *); +extern PyStatus _PyTypes_InitTypes(PyInterpreterState *); +extern void _PyTypes_Fini(PyInterpreterState *); + + +/* other API */ + +// Type attribute lookup cache: speed up attribute and method lookups, +// see _PyType_Lookup(). +struct type_cache_entry { + unsigned int version; // initialized from type->tp_version_tag + PyObject *name; // reference to exactly a str or None + PyObject *value; // borrowed reference or NULL +}; + +#define MCACHE_SIZE_EXP 12 +#define MCACHE_STATS 0 + +struct type_cache { + struct type_cache_entry hashtable[1 << MCACHE_SIZE_EXP]; +#if MCACHE_STATS + size_t hits; + size_t misses; + size_t collisions; +#endif +}; + +extern PyStatus _PyTypes_InitSlotDefs(void); + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_TYPEOBJECT_H */ diff --git a/Include/internal/pycore_unicodeobject.h b/Include/internal/pycore_unicodeobject.h new file mode 100644 index 0000000000..c50c42011a --- /dev/null +++ b/Include/internal/pycore_unicodeobject.h @@ -0,0 +1,71 @@ +#ifndef Py_INTERNAL_UNICODEOBJECT_H +#define Py_INTERNAL_UNICODEOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +/* runtime lifecycle */ + +extern void _PyUnicode_InitState(PyInterpreterState *); +extern PyStatus _PyUnicode_InitGlobalObjects(PyInterpreterState *); +extern PyStatus _PyUnicode_InitTypes(PyInterpreterState *); +extern void _PyUnicode_Fini(PyInterpreterState *); + + +/* other API */ + +struct _Py_unicode_runtime_ids { + PyThread_type_lock lock; + // next_index value must be preserved when Py_Initialize()/Py_Finalize() + // is called multiple times: see _PyUnicode_FromId() implementation. + Py_ssize_t next_index; +}; + +/* fs_codec.encoding is initialized to NULL. + Later, it is set to a non-NULL string by _PyUnicode_InitEncodings(). */ +struct _Py_unicode_fs_codec { + char *encoding; // Filesystem encoding (encoded to UTF-8) + int utf8; // encoding=="utf-8"? + char *errors; // Filesystem errors (encoded to UTF-8) + _Py_error_handler error_handler; +}; + +struct _Py_unicode_ids { + Py_ssize_t size; + PyObject **array; +}; + +struct _Py_unicode_state { + // The empty Unicode object is a singleton to improve performance. + PyObject *empty_string; + /* Single character Unicode strings in the Latin-1 range are being + shared as well. */ + PyObject *latin1[256]; + struct _Py_unicode_fs_codec fs_codec; + + /* This dictionary holds all interned unicode strings. Note that references + to strings in this dictionary are *not* counted in the string's ob_refcnt. + When the interned string reaches a refcnt of 0 the string deallocation + function will delete the reference from this dictionary. + + Another way to look at this is that to say that the actual reference + count of a string is: s->ob_refcnt + (s->state ? 2 : 0) + */ + PyObject *interned; + + // Unicode identifiers (_Py_Identifier): see _PyUnicode_FromId() + struct _Py_unicode_ids ids; +}; + +extern void _PyUnicode_ClearInterned(PyInterpreterState *); + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_UNICODEOBJECT_H */ |