diff --git a/RELEASENOTE.md b/RELEASENOTE.md index 1beab6f1..d06e02ab 100644 --- a/RELEASENOTE.md +++ b/RELEASENOTE.md @@ -1,3 +1,3 @@ -v2.1.2更新 -- 移除了 onMove 事件 -- 更新 SDK \ No newline at end of file +锘縱2.1.3鏇存柊 +- 鏇存柊 python 3.11.0 +- 閫傞厤鏂扮増 LL \ No newline at end of file diff --git a/SDK b/SDK index 9a322417..82842750 160000 --- a/SDK +++ b/SDK @@ -1 +1 @@ -Subproject commit 9a32241740e035feb24f4a02eda5a075cabe9b50 +Subproject commit 8284275017ca2c60be960c6f7e53bc42c9e06298 diff --git a/include/Python.h b/include/Python.h index d3186c32..52a7aac6 100644 --- a/include/Python.h +++ b/include/Python.h @@ -1,88 +1,56 @@ +// Entry point of the Python C API. +// C extensions should only #include , and not include directly +// the other Python header files included by . + #ifndef Py_PYTHON_H #define Py_PYTHON_H -/* Since this is a "meta-include" file, no #ifdef __cplusplus / extern "C" { */ -/* Include nearly all Python header files */ +// Since this is a "meta-include" file, no #ifdef __cplusplus / extern "C" { +// Include Python header files #include "patchlevel.h" #include "pyconfig.h" #include "pymacconfig.h" -#include - -#ifndef UCHAR_MAX -#error "Something's broken. UCHAR_MAX should be defined in limits.h." -#endif - -#if UCHAR_MAX != 255 -#error "Python's source code assumes C's unsigned char is an 8-bit type." -#endif - #if defined(__sgi) && !defined(_SGI_MP_SOURCE) -#define _SGI_MP_SOURCE +# define _SGI_MP_SOURCE #endif -#include -#ifndef NULL -# error "Python.h requires that stdio.h define NULL." +// stdlib.h, stdio.h, errno.h and string.h headers are not used by Python +// headers, but kept for backward compatibility. They are excluded from the +// limited C API of Python 3.11. +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# include +# include // FILE* +# include // errno +# include // memcpy() #endif - -#include -#ifdef HAVE_ERRNO_H -#include -#endif -#include #ifndef MS_WINDOWS -#include +# include #endif - -/* For size_t? */ #ifdef HAVE_STDDEF_H -#include +# include // size_t #endif -/* CAUTION: Build setups should ensure that NDEBUG is defined on the - * compiler command line when building Python in release mode; else - * assert() calls won't be removed. - */ -#include +#include // assert() +#include // wchar_t #include "pyport.h" #include "pymacro.h" - -/* A convenient way for code to know if sanitizers are enabled. */ -#if defined(__has_feature) -# if __has_feature(memory_sanitizer) -# if !defined(_Py_MEMORY_SANITIZER) -# define _Py_MEMORY_SANITIZER -# endif -# endif -# if __has_feature(address_sanitizer) -# if !defined(_Py_ADDRESS_SANITIZER) -# define _Py_ADDRESS_SANITIZER -# endif -# endif -#elif defined(__GNUC__) -# if defined(__SANITIZE_ADDRESS__) -# define _Py_ADDRESS_SANITIZER -# endif -#endif - #include "pymath.h" #include "pymem.h" - +#include "pytypedefs.h" +#include "pybuffer.h" #include "object.h" #include "objimpl.h" #include "typeslots.h" #include "pyhash.h" - #include "cpython/pydebug.h" - #include "bytearrayobject.h" #include "bytesobject.h" #include "unicodeobject.h" #include "longobject.h" -#include "longintrepr.h" +#include "cpython/longintrepr.h" #include "boolobject.h" #include "floatobject.h" #include "complexobject.h" @@ -96,33 +64,30 @@ #include "setobject.h" #include "methodobject.h" #include "moduleobject.h" -#include "funcobject.h" -#include "classobject.h" +#include "cpython/funcobject.h" +#include "cpython/classobject.h" #include "fileobject.h" #include "pycapsule.h" -#include "code.h" +#include "cpython/code.h" #include "pyframe.h" #include "traceback.h" #include "sliceobject.h" -#include "cellobject.h" +#include "cpython/cellobject.h" #include "iterobject.h" #include "cpython/initconfig.h" -#include "genobject.h" +#include "pystate.h" +#include "cpython/genobject.h" #include "descrobject.h" #include "genericaliasobject.h" #include "warnings.h" #include "weakrefobject.h" #include "structseq.h" -#include "namespaceobject.h" #include "cpython/picklebufobject.h" #include "cpython/pytime.h" - #include "codecs.h" #include "pyerrors.h" #include "pythread.h" -#include "pystate.h" -#include "context.h" - +#include "cpython/context.h" #include "modsupport.h" #include "compile.h" #include "pythonrun.h" @@ -132,12 +97,8 @@ #include "osmodule.h" #include "intrcheck.h" #include "import.h" - #include "abstract.h" #include "bltinmodule.h" - -#include "eval.h" - #include "cpython/pyctype.h" #include "pystrtod.h" #include "pystrcmp.h" diff --git a/include/abstract.h b/include/abstract.h index 9eaab6b2..9e06fbbb 100644 --- a/include/abstract.h +++ b/include/abstract.h @@ -863,7 +863,7 @@ PyAPI_FUNC(int) PyObject_IsSubclass(PyObject *object, PyObject *typeorclass); #ifndef Py_LIMITED_API # define Py_CPYTHON_ABSTRACTOBJECT_H -# include "cpython/abstract.h" +# include "cpython/abstract.h" # undef Py_CPYTHON_ABSTRACTOBJECT_H #endif diff --git a/include/boolobject.h b/include/boolobject.h index cda6f89a..28068d1c 100644 --- a/include/boolobject.h +++ b/include/boolobject.h @@ -15,8 +15,8 @@ PyAPI_DATA(PyTypeObject) PyBool_Type; Don't forget to apply Py_INCREF() when returning either!!! */ /* Don't use these directly */ -PyAPI_DATA(struct _longobject) _Py_FalseStruct; -PyAPI_DATA(struct _longobject) _Py_TrueStruct; +PyAPI_DATA(PyLongObject) _Py_FalseStruct; +PyAPI_DATA(PyLongObject) _Py_TrueStruct; /* Use these macros */ #define Py_False ((PyObject *) &_Py_FalseStruct) diff --git a/include/bytearrayobject.h b/include/bytearrayobject.h index 9e95433f..ae2bde1c 100644 --- a/include/bytearrayobject.h +++ b/include/bytearrayobject.h @@ -6,8 +6,6 @@ extern "C" { #endif -#include - /* Type PyByteArrayObject represents a mutable array of bytes. * The Python API is that of a sequence; * the bytes are mapped to ints in [0, 256). @@ -36,7 +34,7 @@ PyAPI_FUNC(int) PyByteArray_Resize(PyObject *, Py_ssize_t); #ifndef Py_LIMITED_API # define Py_CPYTHON_BYTEARRAYOBJECT_H -# include "cpython/bytearrayobject.h" +# include "cpython/bytearrayobject.h" # undef Py_CPYTHON_BYTEARRAYOBJECT_H #endif diff --git a/include/bytesobject.h b/include/bytesobject.h index 39c241a2..4c4dc40d 100644 --- a/include/bytesobject.h +++ b/include/bytesobject.h @@ -7,7 +7,7 @@ extern "C" { #endif -#include +#include // va_list /* Type PyBytesObject represents a byte string. An extra zero byte is @@ -59,7 +59,7 @@ PyAPI_FUNC(int) PyBytes_AsStringAndSize( #ifndef Py_LIMITED_API # define Py_CPYTHON_BYTESOBJECT_H -# include "cpython/bytesobject.h" +# include "cpython/bytesobject.h" # undef Py_CPYTHON_BYTESOBJECT_H #endif diff --git a/include/ceval.h b/include/ceval.h index 0f687666..1b57f6ea 100644 --- a/include/ceval.h +++ b/include/ceval.h @@ -1,3 +1,5 @@ +/* Interface to random parts in ceval.c */ + #ifndef Py_CEVAL_H #define Py_CEVAL_H #ifdef __cplusplus @@ -5,7 +7,15 @@ extern "C" { #endif -/* Interface to random parts in ceval.c */ +PyAPI_FUNC(PyObject *) PyEval_EvalCode(PyObject *, PyObject *, PyObject *); + +PyAPI_FUNC(PyObject *) PyEval_EvalCodeEx(PyObject *co, + PyObject *globals, + PyObject *locals, + PyObject *const *args, int argc, + PyObject *const *kwds, int kwdc, + PyObject *const *defs, int defc, + PyObject *kwdefs, PyObject *closure); /* PyEval_CallObjectWithKeywords(), PyEval_CallObject(), PyEval_CallFunction * and PyEval_CallMethod are deprecated. Since they are officially part of the @@ -148,7 +158,7 @@ PyAPI_FUNC(void) PyEval_ReleaseThread(PyThreadState *tstate); #ifndef Py_LIMITED_API # define Py_CPYTHON_CEVAL_H -# include "cpython/ceval.h" +# include "cpython/ceval.h" # undef Py_CPYTHON_CEVAL_H #endif diff --git a/include/code.h b/include/code.h deleted file mode 100644 index b9e23eb8..00000000 --- a/include/code.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Definitions for bytecode */ - -#ifndef Py_CODE_H -#define Py_CODE_H -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct PyCodeObject PyCodeObject; - -#ifndef Py_LIMITED_API -# define Py_CPYTHON_CODE_H -# include "cpython/code.h" -# undef Py_CPYTHON_CODE_H -#endif - -#ifdef __cplusplus -} -#endif -#endif /* !Py_CODE_H */ diff --git a/include/complexobject.h b/include/complexobject.h index 9221f9c5..c7764e43 100644 --- a/include/complexobject.h +++ b/include/complexobject.h @@ -6,61 +6,22 @@ extern "C" { #endif -#ifndef Py_LIMITED_API -typedef struct { - double real; - double imag; -} Py_complex; - -/* Operations on complex numbers from complexmodule.c */ - -PyAPI_FUNC(Py_complex) _Py_c_sum(Py_complex, Py_complex); -PyAPI_FUNC(Py_complex) _Py_c_diff(Py_complex, Py_complex); -PyAPI_FUNC(Py_complex) _Py_c_neg(Py_complex); -PyAPI_FUNC(Py_complex) _Py_c_prod(Py_complex, Py_complex); -PyAPI_FUNC(Py_complex) _Py_c_quot(Py_complex, Py_complex); -PyAPI_FUNC(Py_complex) _Py_c_pow(Py_complex, Py_complex); -PyAPI_FUNC(double) _Py_c_abs(Py_complex); -#endif - /* Complex object interface */ -/* -PyComplexObject represents a complex number with double-precision -real and imaginary parts. -*/ -#ifndef Py_LIMITED_API -typedef struct { - PyObject_HEAD - Py_complex cval; -} PyComplexObject; -#endif - PyAPI_DATA(PyTypeObject) PyComplex_Type; #define PyComplex_Check(op) PyObject_TypeCheck(op, &PyComplex_Type) #define PyComplex_CheckExact(op) Py_IS_TYPE(op, &PyComplex_Type) -#ifndef Py_LIMITED_API -PyAPI_FUNC(PyObject *) PyComplex_FromCComplex(Py_complex); -#endif PyAPI_FUNC(PyObject *) PyComplex_FromDoubles(double real, double imag); PyAPI_FUNC(double) PyComplex_RealAsDouble(PyObject *op); PyAPI_FUNC(double) PyComplex_ImagAsDouble(PyObject *op); -#ifndef Py_LIMITED_API -PyAPI_FUNC(Py_complex) PyComplex_AsCComplex(PyObject *op); -#endif -/* Format the object based on the format_spec, as defined in PEP 3101 - (Advanced String Formatting). */ #ifndef Py_LIMITED_API -PyAPI_FUNC(int) _PyComplex_FormatAdvancedWriter( - _PyUnicodeWriter *writer, - PyObject *obj, - PyObject *format_spec, - Py_ssize_t start, - Py_ssize_t end); +# define Py_CPYTHON_COMPLEXOBJECT_H +# include "cpython/complexobject.h" +# undef Py_CPYTHON_COMPLEXOBJECT_H #endif #ifdef __cplusplus diff --git a/include/cpython/abstract.h b/include/cpython/abstract.h index db850219..d2766693 100644 --- a/include/cpython/abstract.h +++ b/include/cpython/abstract.h @@ -50,7 +50,8 @@ PyAPI_FUNC(PyObject *) _PyObject_MakeTpCall( PyObject *const *args, Py_ssize_t nargs, PyObject *keywords); -#define PY_VECTORCALL_ARGUMENTS_OFFSET ((size_t)1 << (8 * sizeof(size_t) - 1)) +#define PY_VECTORCALL_ARGUMENTS_OFFSET \ + (_Py_STATIC_CAST(size_t, 1) << (8 * sizeof(size_t) - 1)) static inline Py_ssize_t PyVectorcall_NARGS(size_t n) @@ -58,71 +59,13 @@ PyVectorcall_NARGS(size_t n) return n & ~PY_VECTORCALL_ARGUMENTS_OFFSET; } -static inline vectorcallfunc -PyVectorcall_Function(PyObject *callable) -{ - PyTypeObject *tp; - Py_ssize_t offset; - vectorcallfunc ptr; - - assert(callable != NULL); - tp = Py_TYPE(callable); - if (!PyType_HasFeature(tp, Py_TPFLAGS_HAVE_VECTORCALL)) { - return NULL; - } - assert(PyCallable_Check(callable)); - offset = tp->tp_vectorcall_offset; - assert(offset > 0); - memcpy(&ptr, (char *) callable + offset, sizeof(ptr)); - return ptr; -} - -/* Call the callable object 'callable' with the "vectorcall" calling - convention. - - args is a C array for positional arguments. - - nargsf is the number of positional arguments plus optionally the flag - PY_VECTORCALL_ARGUMENTS_OFFSET which means that the caller is allowed to - modify args[-1]. - - kwnames is a tuple of keyword names. The values of the keyword arguments - are stored in "args" after the positional arguments (note that the number - of keyword arguments does not change nargsf). kwnames can also be NULL if - there are no keyword arguments. - - keywords must only contain strings and all keys must be unique. - - Return the result on success. Raise an exception and return NULL on - error. */ -static inline PyObject * -_PyObject_VectorcallTstate(PyThreadState *tstate, PyObject *callable, - PyObject *const *args, size_t nargsf, - PyObject *kwnames) -{ - vectorcallfunc func; - PyObject *res; +PyAPI_FUNC(vectorcallfunc) PyVectorcall_Function(PyObject *callable); - assert(kwnames == NULL || PyTuple_Check(kwnames)); - assert(args != NULL || PyVectorcall_NARGS(nargsf) == 0); - - func = PyVectorcall_Function(callable); - if (func == NULL) { - Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); - return _PyObject_MakeTpCall(tstate, callable, args, nargs, kwnames); - } - res = func(callable, args, nargsf, kwnames); - return _Py_CheckFunctionResult(tstate, callable, res, NULL); -} - -static inline PyObject * -PyObject_Vectorcall(PyObject *callable, PyObject *const *args, - size_t nargsf, PyObject *kwnames) -{ - PyThreadState *tstate = PyThreadState_Get(); - return _PyObject_VectorcallTstate(tstate, callable, - args, nargsf, kwnames); -} +PyAPI_FUNC(PyObject *) PyObject_Vectorcall( + PyObject *callable, + PyObject *const *args, + size_t nargsf, + PyObject *kwnames); // Backwards compatibility aliases for API that was provisional in Python 3.8 #define _PyObject_Vectorcall PyObject_Vectorcall @@ -145,44 +88,13 @@ PyAPI_FUNC(PyObject *) PyObject_VectorcallDict( "tuple" and keyword arguments "dict". "dict" may also be NULL */ PyAPI_FUNC(PyObject *) PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *dict); -static inline PyObject * -_PyObject_FastCallTstate(PyThreadState *tstate, PyObject *func, PyObject *const *args, Py_ssize_t nargs) -{ - return _PyObject_VectorcallTstate(tstate, func, args, (size_t)nargs, NULL); -} - -/* Same as PyObject_Vectorcall except without keyword arguments */ -static inline PyObject * -_PyObject_FastCall(PyObject *func, PyObject *const *args, Py_ssize_t nargs) -{ - PyThreadState *tstate = PyThreadState_Get(); - return _PyObject_FastCallTstate(tstate, func, args, nargs); -} - -/* Call a callable without any arguments - Private static inline function variant of public function - PyObject_CallNoArgs(). */ -static inline PyObject * -_PyObject_CallNoArg(PyObject *func) { - PyThreadState *tstate = PyThreadState_Get(); - return _PyObject_VectorcallTstate(tstate, func, NULL, 0, NULL); -} - -static inline PyObject * -PyObject_CallOneArg(PyObject *func, PyObject *arg) -{ - PyObject *_args[2]; - PyObject **args; - PyThreadState *tstate; - size_t nargsf; +// Same as PyObject_Vectorcall(), except without keyword arguments +PyAPI_FUNC(PyObject *) _PyObject_FastCall( + PyObject *func, + PyObject *const *args, + Py_ssize_t nargs); - assert(arg != NULL); - args = _args + 1; // For PY_VECTORCALL_ARGUMENTS_OFFSET - args[0] = arg; - tstate = PyThreadState_Get(); - nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET; - return _PyObject_VectorcallTstate(tstate, func, args, nargsf, NULL); -} +PyAPI_FUNC(PyObject *) PyObject_CallOneArg(PyObject *func, PyObject *arg); PyAPI_FUNC(PyObject *) PyObject_VectorcallMethod( PyObject *name, PyObject *const *args, @@ -191,20 +103,23 @@ PyAPI_FUNC(PyObject *) PyObject_VectorcallMethod( static inline PyObject * PyObject_CallMethodNoArgs(PyObject *self, PyObject *name) { - return PyObject_VectorcallMethod(name, &self, - 1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); + size_t nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET; + return PyObject_VectorcallMethod(name, &self, nargsf, _Py_NULL); } static inline PyObject * PyObject_CallMethodOneArg(PyObject *self, PyObject *name, PyObject *arg) { PyObject *args[2] = {self, arg}; - + size_t nargsf = 2 | PY_VECTORCALL_ARGUMENTS_OFFSET; assert(arg != NULL); - return PyObject_VectorcallMethod(name, args, - 2 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); + return PyObject_VectorcallMethod(name, args, nargsf, _Py_NULL); } +PyAPI_FUNC(PyObject *) _PyObject_CallMethod(PyObject *obj, + PyObject *name, + const char *format, ...); + /* Like PyObject_CallMethod(), but expect a _Py_Identifier* as the method name. */ PyAPI_FUNC(PyObject *) _PyObject_CallMethodId(PyObject *obj, @@ -218,7 +133,7 @@ PyAPI_FUNC(PyObject *) _PyObject_CallMethodId_SizeT(PyObject *obj, PyAPI_FUNC(PyObject *) _PyObject_CallMethodIdObjArgs( PyObject *obj, - struct _Py_Identifier *name, + _Py_Identifier *name, ...); static inline PyObject * @@ -228,7 +143,7 @@ _PyObject_VectorcallMethodId( { PyObject *oname = _PyUnicode_FromId(name); /* borrowed */ if (!oname) { - return NULL; + return _Py_NULL; } return PyObject_VectorcallMethod(oname, args, nargsf, kwnames); } @@ -236,18 +151,17 @@ _PyObject_VectorcallMethodId( static inline PyObject * _PyObject_CallMethodIdNoArgs(PyObject *self, _Py_Identifier *name) { - return _PyObject_VectorcallMethodId(name, &self, - 1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); + size_t nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET; + return _PyObject_VectorcallMethodId(name, &self, nargsf, _Py_NULL); } static inline PyObject * _PyObject_CallMethodIdOneArg(PyObject *self, _Py_Identifier *name, PyObject *arg) { PyObject *args[2] = {self, arg}; - + size_t nargsf = 2 | PY_VECTORCALL_ARGUMENTS_OFFSET; assert(arg != NULL); - return _PyObject_VectorcallMethodId(name, args, - 2 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); + return _PyObject_VectorcallMethodId(name, args, nargsf, _Py_NULL); } PyAPI_FUNC(int) _PyObject_HasLen(PyObject *o); @@ -257,74 +171,6 @@ PyAPI_FUNC(int) _PyObject_HasLen(PyObject *o); value. If one of the calls fails, this function returns -1. */ PyAPI_FUNC(Py_ssize_t) PyObject_LengthHint(PyObject *o, Py_ssize_t); -/* === New Buffer API ============================================ */ - -/* Return 1 if the getbuffer function is available, otherwise return 0. */ -PyAPI_FUNC(int) PyObject_CheckBuffer(PyObject *obj); - -/* This is a C-API version of the getbuffer function call. It checks - to make sure object has the required function pointer and issues the - call. - - Returns -1 and raises an error on failure and returns 0 on success. */ -PyAPI_FUNC(int) PyObject_GetBuffer(PyObject *obj, Py_buffer *view, - int flags); - -/* Get the memory area pointed to by the indices for the buffer given. - Note that view->ndim is the assumed size of indices. */ -PyAPI_FUNC(void *) PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices); - -/* Return the implied itemsize of the data-format area from a - struct-style description. */ -PyAPI_FUNC(Py_ssize_t) PyBuffer_SizeFromFormat(const char *format); - -/* Implementation in memoryobject.c */ -PyAPI_FUNC(int) PyBuffer_ToContiguous(void *buf, Py_buffer *view, - Py_ssize_t len, char order); - -PyAPI_FUNC(int) PyBuffer_FromContiguous(Py_buffer *view, void *buf, - Py_ssize_t len, char order); - -/* Copy len bytes of data from the contiguous chunk of memory - pointed to by buf into the buffer exported by obj. Return - 0 on success and return -1 and raise a PyBuffer_Error on - error (i.e. the object does not have a buffer interface or - it is not working). - - If fort is 'F', then if the object is multi-dimensional, - then the data will be copied into the array in - Fortran-style (first dimension varies the fastest). If - fort is 'C', then the data will be copied into the array - in C-style (last dimension varies the fastest). If fort - is 'A', then it does not matter and the copy will be made - in whatever way is more efficient. */ -PyAPI_FUNC(int) PyObject_CopyData(PyObject *dest, PyObject *src); - -/* Copy the data from the src buffer to the buffer of destination. */ -PyAPI_FUNC(int) PyBuffer_IsContiguous(const Py_buffer *view, char fort); - -/*Fill the strides array with byte-strides of a contiguous - (Fortran-style if fort is 'F' or C-style otherwise) - array of the given shape with the given number of bytes - per element. */ -PyAPI_FUNC(void) PyBuffer_FillContiguousStrides(int ndims, - Py_ssize_t *shape, - Py_ssize_t *strides, - int itemsize, - char fort); - -/* Fills in a buffer-info structure correctly for an exporter - that can only share a contiguous chunk of memory of - "unsigned bytes" of the given length. - - Returns 0 on success and -1 (with raising an error) on error. */ -PyAPI_FUNC(int) PyBuffer_FillInfo(Py_buffer *view, PyObject *o, void *buf, - Py_ssize_t len, int readonly, - int flags); - -/* Releases a Py_buffer obtained from getbuffer ParseTuple's "s*". */ -PyAPI_FUNC(void) PyBuffer_Release(Py_buffer *view); - /* === Sequence protocol ================================================ */ /* Assume tp_as_sequence and sq_item exist and that 'i' does not diff --git a/include/cpython/bytearrayobject.h b/include/cpython/bytearrayobject.h index 569b0cd0..5114169c 100644 --- a/include/cpython/bytearrayobject.h +++ b/include/cpython/bytearrayobject.h @@ -11,10 +11,28 @@ typedef struct { Py_ssize_t ob_exports; /* How many buffer exports */ } PyByteArrayObject; -/* Macros, trading safety for speed */ -#define PyByteArray_AS_STRING(self) \ - (assert(PyByteArray_Check(self)), \ - Py_SIZE(self) ? ((PyByteArrayObject *)(self))->ob_start : _PyByteArray_empty_string) -#define PyByteArray_GET_SIZE(self) (assert(PyByteArray_Check(self)), Py_SIZE(self)) - PyAPI_DATA(char) _PyByteArray_empty_string[]; + +/* Macros and static inline functions, trading safety for speed */ +#define _PyByteArray_CAST(op) \ + (assert(PyByteArray_Check(op)), _Py_CAST(PyByteArrayObject*, op)) + +static inline char* PyByteArray_AS_STRING(PyObject *op) +{ + PyByteArrayObject *self = _PyByteArray_CAST(op); + if (Py_SIZE(self)) { + return self->ob_start; + } + return _PyByteArray_empty_string; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyByteArray_AS_STRING(self) PyByteArray_AS_STRING(_PyObject_CAST(self)) +#endif + +static inline Py_ssize_t PyByteArray_GET_SIZE(PyObject *op) { + PyByteArrayObject *self = _PyByteArray_CAST(op); + return Py_SIZE(self); +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyByteArray_GET_SIZE(self) PyByteArray_GET_SIZE(_PyObject_CAST(self)) +#endif diff --git a/include/cpython/bytesobject.h b/include/cpython/bytesobject.h index 6b3f5522..53343661 100644 --- a/include/cpython/bytesobject.h +++ b/include/cpython/bytesobject.h @@ -4,7 +4,7 @@ typedef struct { PyObject_VAR_HEAD - Py_hash_t ob_shash; + Py_DEPRECATED(3.11) Py_hash_t ob_shash; char ob_sval[1]; /* Invariants: @@ -28,10 +28,25 @@ PyAPI_FUNC(PyObject*) _PyBytes_FromHex( PyAPI_FUNC(PyObject *) _PyBytes_DecodeEscape(const char *, Py_ssize_t, const char *, const char **); -/* Macro, trading safety for speed */ -#define PyBytes_AS_STRING(op) (assert(PyBytes_Check(op)), \ - (((PyBytesObject *)(op))->ob_sval)) -#define PyBytes_GET_SIZE(op) (assert(PyBytes_Check(op)),Py_SIZE(op)) +/* Macros and static inline functions, trading safety for speed */ +#define _PyBytes_CAST(op) \ + (assert(PyBytes_Check(op)), _Py_CAST(PyBytesObject*, op)) + +static inline char* PyBytes_AS_STRING(PyObject *op) +{ + return _PyBytes_CAST(op)->ob_sval; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyBytes_AS_STRING(op) PyBytes_AS_STRING(_PyObject_CAST(op)) +#endif + +static inline Py_ssize_t PyBytes_GET_SIZE(PyObject *op) { + PyBytesObject *self = _PyBytes_CAST(op); + return Py_SIZE(self); +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyBytes_GET_SIZE(self) PyBytes_GET_SIZE(_PyObject_CAST(self)) +#endif /* _PyBytes_Join(sep, x) is like sep.join(x). sep must be PyBytesObject*, x must be an iterable object. */ diff --git a/include/cellobject.h b/include/cpython/cellobject.h similarity index 79% rename from include/cellobject.h rename to include/cpython/cellobject.h index 81bc784d..e07f9d1d 100644 --- a/include/cellobject.h +++ b/include/cpython/cellobject.h @@ -1,4 +1,5 @@ /* Cell object interface */ + #ifndef Py_LIMITED_API #ifndef Py_CELLOBJECT_H #define Py_CELLOBJECT_H @@ -8,7 +9,8 @@ extern "C" { typedef struct { PyObject_HEAD - PyObject *ob_ref; /* Content of the cell or NULL when empty */ + /* Content of the cell or NULL when empty */ + PyObject *ob_ref; } PyCellObject; PyAPI_DATA(PyTypeObject) PyCell_Type; @@ -20,7 +22,7 @@ PyAPI_FUNC(PyObject *) PyCell_Get(PyObject *); PyAPI_FUNC(int) PyCell_Set(PyObject *, PyObject *); #define PyCell_GET(op) (((PyCellObject *)(op))->ob_ref) -#define PyCell_SET(op, v) ((void)(((PyCellObject *)(op))->ob_ref = v)) +#define PyCell_SET(op, v) _Py_RVALUE(((PyCellObject *)(op))->ob_ref = (v)) #ifdef __cplusplus } diff --git a/include/cpython/ceval.h b/include/cpython/ceval.h index 06338928..9d4eeafb 100644 --- a/include/cpython/ceval.h +++ b/include/cpython/ceval.h @@ -6,20 +6,16 @@ PyAPI_FUNC(void) PyEval_SetProfile(Py_tracefunc, PyObject *); PyAPI_DATA(int) _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg); PyAPI_FUNC(void) PyEval_SetTrace(Py_tracefunc, PyObject *); PyAPI_FUNC(int) _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg); -PyAPI_FUNC(int) _PyEval_GetCoroutineOriginTrackingDepth(void); -PyAPI_FUNC(int) _PyEval_SetAsyncGenFirstiter(PyObject *); -PyAPI_FUNC(PyObject *) _PyEval_GetAsyncGenFirstiter(void); -PyAPI_FUNC(int) _PyEval_SetAsyncGenFinalizer(PyObject *); -PyAPI_FUNC(PyObject *) _PyEval_GetAsyncGenFinalizer(void); /* Helper to look up a builtin object */ +PyAPI_FUNC(PyObject *) _PyEval_GetBuiltin(PyObject *); PyAPI_FUNC(PyObject *) _PyEval_GetBuiltinId(_Py_Identifier *); /* Look at the current frame's (if any) code's co_flags, and turn on the corresponding compiler flags in cf->cf_flags. Return 1 if any flag was set, else return 0. */ PyAPI_FUNC(int) PyEval_MergeCompilerFlags(PyCompilerFlags *cf); -PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int exc); +PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc); PyAPI_FUNC(void) _PyEval_SetSwitchInterval(unsigned long microseconds); PyAPI_FUNC(unsigned long) _PyEval_GetSwitchInterval(void); diff --git a/include/classobject.h b/include/cpython/classobject.h similarity index 96% rename from include/classobject.h rename to include/cpython/classobject.h index 1952f673..80df8842 100644 --- a/include/classobject.h +++ b/include/cpython/classobject.h @@ -53,5 +53,5 @@ PyAPI_FUNC(PyObject *) PyInstanceMethod_Function(PyObject *); #ifdef __cplusplus } #endif -#endif /* !Py_CLASSOBJECT_H */ -#endif /* Py_LIMITED_API */ +#endif // !Py_CLASSOBJECT_H +#endif // !Py_LIMITED_API diff --git a/include/cpython/code.h b/include/cpython/code.h index fa640852..7006060c 100644 --- a/include/cpython/code.h +++ b/include/cpython/code.h @@ -1,67 +1,106 @@ -#ifndef Py_CPYTHON_CODE_H -# error "this header file must not be included directly" +/* Definitions for bytecode */ + +#ifndef Py_LIMITED_API +#ifndef Py_CODE_H +#define Py_CODE_H +#ifdef __cplusplus +extern "C" { #endif +/* Each instruction in a code object is a fixed-width value, + * currently 2 bytes: 1-byte opcode + 1-byte oparg. The EXTENDED_ARG + * opcode allows for larger values but the current limit is 3 uses + * of EXTENDED_ARG (see Python/compile.c), for a maximum + * 32-bit value. This aligns with the note in Python/compile.c + * (compiler_addop_i_line) indicating that the max oparg value is + * 2**32 - 1, rather than INT_MAX. + */ + typedef uint16_t _Py_CODEUNIT; #ifdef WORDS_BIGENDIAN # define _Py_OPCODE(word) ((word) >> 8) # define _Py_OPARG(word) ((word) & 255) +# define _Py_MAKECODEUNIT(opcode, oparg) (((opcode)<<8)|(oparg)) #else # define _Py_OPCODE(word) ((word) & 255) # define _Py_OPARG(word) ((word) >> 8) +# define _Py_MAKECODEUNIT(opcode, oparg) ((opcode)|((oparg)<<8)) #endif -typedef struct _PyOpcache _PyOpcache; +// Use "unsigned char" instead of "uint8_t" here to avoid illegal aliasing: +#define _Py_SET_OPCODE(word, opcode) (((unsigned char *)&(word))[0] = (opcode)) + +// To avoid repeating ourselves in deepfreeze.py, all PyCodeObject members are +// defined in this macro: +#define _PyCode_DEF(SIZE) { \ + PyObject_VAR_HEAD \ + \ + /* Note only the following fields are used in hash and/or comparisons \ + * \ + * - co_name \ + * - co_argcount \ + * - co_posonlyargcount \ + * - co_kwonlyargcount \ + * - co_nlocals \ + * - co_stacksize \ + * - co_flags \ + * - co_firstlineno \ + * - co_consts \ + * - co_names \ + * - co_localsplusnames \ + * This is done to preserve the name and line number for tracebacks \ + * and debuggers; otherwise, constant de-duplication would collapse \ + * identical functions/lambdas defined on different lines. \ + */ \ + \ + /* These fields are set with provided values on new code objects. */ \ + \ + /* The hottest fields (in the eval loop) are grouped here at the top. */ \ + PyObject *co_consts; /* list (constants used) */ \ + PyObject *co_names; /* list of strings (names used) */ \ + PyObject *co_exceptiontable; /* Byte string encoding exception handling \ + table */ \ + int co_flags; /* CO_..., see below */ \ + short co_warmup; /* Warmup counter for quickening */ \ + short _co_linearray_entry_size; /* Size of each entry in _co_linearray */ \ + \ + /* The rest are not so impactful on performance. */ \ + int co_argcount; /* #arguments, except *args */ \ + int co_posonlyargcount; /* #positional only arguments */ \ + int co_kwonlyargcount; /* #keyword only arguments */ \ + int co_stacksize; /* #entries needed for evaluation stack */ \ + int co_firstlineno; /* first source line number */ \ + \ + /* redundant values (derived from co_localsplusnames and \ + co_localspluskinds) */ \ + int co_nlocalsplus; /* number of local + cell + free variables \ + */ \ + int co_nlocals; /* number of local variables */ \ + int co_nplaincellvars; /* number of non-arg cell variables */ \ + int co_ncellvars; /* total number of cell variables */ \ + int co_nfreevars; /* number of free variables */ \ + \ + PyObject *co_localsplusnames; /* tuple mapping offsets to names */ \ + PyObject *co_localspluskinds; /* Bytes mapping to local kinds (one byte \ + per variable) */ \ + PyObject *co_filename; /* unicode (where it was loaded from) */ \ + PyObject *co_name; /* unicode (name, for reference) */ \ + PyObject *co_qualname; /* unicode (qualname, for reference) */ \ + PyObject *co_linetable; /* bytes object that holds location info */ \ + PyObject *co_weakreflist; /* to support weakrefs to code objects */ \ + PyObject *_co_code; /* cached co_code object/attribute */ \ + char *_co_linearray; /* array of line offsets */ \ + int _co_firsttraceable; /* index of first traceable instruction */ \ + /* Scratch space for extra data relating to the code object. \ + Type is a void* to keep the format private in codeobject.c to force \ + people to go through the proper APIs. */ \ + void *co_extra; \ + char co_code_adaptive[(SIZE)]; \ +} /* Bytecode object */ -struct PyCodeObject { - PyObject_HEAD - int co_argcount; /* #arguments, except *args */ - int co_posonlyargcount; /* #positional only arguments */ - int co_kwonlyargcount; /* #keyword only arguments */ - int co_nlocals; /* #local variables */ - int co_stacksize; /* #entries needed for evaluation stack */ - int co_flags; /* CO_..., see below */ - int co_firstlineno; /* first source line number */ - PyObject *co_code; /* instruction opcodes */ - PyObject *co_consts; /* list (constants used) */ - PyObject *co_names; /* list of strings (names used) */ - PyObject *co_varnames; /* tuple of strings (local variable names) */ - PyObject *co_freevars; /* tuple of strings (free variable names) */ - PyObject *co_cellvars; /* tuple of strings (cell variable names) */ - /* The rest aren't used in either hash or comparisons, except for co_name, - used in both. This is done to preserve the name and line number - for tracebacks and debuggers; otherwise, constant de-duplication - would collapse identical functions/lambdas defined on different lines. - */ - Py_ssize_t *co_cell2arg; /* Maps cell vars which are arguments. */ - PyObject *co_filename; /* unicode (where it was loaded from) */ - PyObject *co_name; /* unicode (name, for reference) */ - PyObject *co_linetable; /* string (encoding addr<->lineno mapping) See - Objects/lnotab_notes.txt for details. */ - void *co_zombieframe; /* for optimization only (see frameobject.c) */ - PyObject *co_weakreflist; /* to support weakrefs to code objects */ - /* Scratch space for extra data relating to the code object. - Type is a void* to keep the format private in codeobject.c to force - people to go through the proper APIs. */ - void *co_extra; - - /* Per opcodes just-in-time cache - * - * To reduce cache size, we use indirect mapping from opcode index to - * cache object: - * cache = co_opcache[co_opcache_map[next_instr - first_instr] - 1] - */ - - // co_opcache_map is indexed by (next_instr - first_instr). - // * 0 means there is no cache for this opcode. - // * n > 0 means there is cache in co_opcache[n-1]. - unsigned char *co_opcache_map; - _PyOpcache *co_opcache; - int co_opcache_flag; // used to determine when create a cache. - unsigned char co_opcache_size; // length of co_opcache. -}; +struct PyCodeObject _PyCode_DEF(1); /* Masks for co_flags above */ #define CO_OPTIMIZED 0x0001 @@ -70,12 +109,6 @@ struct PyCodeObject { #define CO_VARKEYWORDS 0x0008 #define CO_NESTED 0x0010 #define CO_GENERATOR 0x0020 -/* The CO_NOFREE flag is set if there are no free or cell variables. - This information is redundant, but it allows a single flag test - to determine whether there is any extra work to be done when the - call frame it setup. -*/ -#define CO_NOFREE 0x0040 /* The CO_COROUTINE flag is set for coroutine functions (defined with ``async def`` keywords) */ @@ -97,10 +130,6 @@ struct PyCodeObject { #define CO_FUTURE_GENERATOR_STOP 0x800000 #define CO_FUTURE_ANNOTATIONS 0x1000000 -/* This value is found in the co_cell2arg array when the associated cell - variable does not correspond to an argument. */ -#define CO_CELL_NOT_AN_ARG (-1) - /* This should be defined if a future statement modifies the syntax. For example, when a keyword is added. */ @@ -111,18 +140,22 @@ struct PyCodeObject { PyAPI_DATA(PyTypeObject) PyCode_Type; #define PyCode_Check(op) Py_IS_TYPE(op, &PyCode_Type) -#define PyCode_GetNumFree(op) (PyTuple_GET_SIZE((op)->co_freevars)) +#define PyCode_GetNumFree(op) ((op)->co_nfreevars) +#define _PyCode_CODE(CO) ((_Py_CODEUNIT *)(CO)->co_code_adaptive) +#define _PyCode_NBYTES(CO) (Py_SIZE(CO) * (Py_ssize_t)sizeof(_Py_CODEUNIT)) /* Public interface */ PyAPI_FUNC(PyCodeObject *) PyCode_New( int, int, int, int, int, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *, - PyObject *, PyObject *, int, PyObject *); + PyObject *, PyObject *, PyObject *, int, PyObject *, + PyObject *); PyAPI_FUNC(PyCodeObject *) PyCode_NewWithPosOnlyArgs( int, int, int, int, int, int, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *, - PyObject *, PyObject *, int, PyObject *); + PyObject *, PyObject *, PyObject *, int, PyObject *, + PyObject *); /* same as struct above */ /* Creates a new empty code object with the specified source location. */ @@ -134,11 +167,13 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno); use PyFrame_GetLineNumber() instead. */ PyAPI_FUNC(int) PyCode_Addr2Line(PyCodeObject *, int); +PyAPI_FUNC(int) PyCode_Addr2Location(PyCodeObject *, int, int *, int *, int *, int *); + /* for internal use only */ struct _opaque { int computed_line; - const char *lo_next; - const char *limit; + const uint8_t *lo_next; + const uint8_t *limit; }; typedef struct _line_offsets { @@ -171,14 +206,31 @@ PyAPI_FUNC(int) _PyCode_GetExtra(PyObject *code, Py_ssize_t index, PyAPI_FUNC(int) _PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra); -/** API for initializing the line number table. */ -int _PyCode_InitAddressRange(PyCodeObject* co, PyCodeAddressRange *bounds); - -/** Out of process API for initializing the line number table. */ -void PyLineTable_InitAddressRange(const char *linetable, Py_ssize_t length, int firstlineno, PyCodeAddressRange *range); - -/** API for traversing the line number table. */ -int PyLineTable_NextAddressRange(PyCodeAddressRange *range); -int PyLineTable_PreviousAddressRange(PyCodeAddressRange *range); - - +/* Equivalent to getattr(code, 'co_code') in Python. + Returns a strong reference to a bytes object. */ +PyAPI_FUNC(PyObject *) PyCode_GetCode(PyCodeObject *code); +/* Equivalent to getattr(code, 'co_varnames') in Python. */ +PyAPI_FUNC(PyObject *) PyCode_GetVarnames(PyCodeObject *code); +/* Equivalent to getattr(code, 'co_cellvars') in Python. */ +PyAPI_FUNC(PyObject *) PyCode_GetCellvars(PyCodeObject *code); +/* Equivalent to getattr(code, 'co_freevars') in Python. */ +PyAPI_FUNC(PyObject *) PyCode_GetFreevars(PyCodeObject *code); + +typedef enum _PyCodeLocationInfoKind { + /* short forms are 0 to 9 */ + PY_CODE_LOCATION_INFO_SHORT0 = 0, + /* one lineforms are 10 to 12 */ + PY_CODE_LOCATION_INFO_ONE_LINE0 = 10, + PY_CODE_LOCATION_INFO_ONE_LINE1 = 11, + PY_CODE_LOCATION_INFO_ONE_LINE2 = 12, + + PY_CODE_LOCATION_INFO_NO_COLUMNS = 13, + PY_CODE_LOCATION_INFO_LONG = 14, + PY_CODE_LOCATION_INFO_NONE = 15 +} _PyCodeLocationInfoKind; + +#ifdef __cplusplus +} +#endif +#endif // !Py_CODE_H +#endif // !Py_LIMITED_API diff --git a/include/cpython/complexobject.h b/include/cpython/complexobject.h new file mode 100644 index 00000000..b7d7283a --- /dev/null +++ b/include/cpython/complexobject.h @@ -0,0 +1,44 @@ +#ifndef Py_CPYTHON_COMPLEXOBJECT_H +# error "this header file must not be included directly" +#endif + +typedef struct { + double real; + double imag; +} Py_complex; + +/* Operations on complex numbers from complexmodule.c */ + +PyAPI_FUNC(Py_complex) _Py_c_sum(Py_complex, Py_complex); +PyAPI_FUNC(Py_complex) _Py_c_diff(Py_complex, Py_complex); +PyAPI_FUNC(Py_complex) _Py_c_neg(Py_complex); +PyAPI_FUNC(Py_complex) _Py_c_prod(Py_complex, Py_complex); +PyAPI_FUNC(Py_complex) _Py_c_quot(Py_complex, Py_complex); +PyAPI_FUNC(Py_complex) _Py_c_pow(Py_complex, Py_complex); +PyAPI_FUNC(double) _Py_c_abs(Py_complex); + +/* Complex object interface */ + +/* +PyComplexObject represents a complex number with double-precision +real and imaginary parts. +*/ +typedef struct { + PyObject_HEAD + Py_complex cval; +} PyComplexObject; + +PyAPI_FUNC(PyObject *) PyComplex_FromCComplex(Py_complex); + +PyAPI_FUNC(Py_complex) PyComplex_AsCComplex(PyObject *op); + +#ifdef Py_BUILD_CORE +/* Format the object based on the format_spec, as defined in PEP 3101 + (Advanced String Formatting). */ +extern int _PyComplex_FormatAdvancedWriter( + _PyUnicodeWriter *writer, + PyObject *obj, + PyObject *format_spec, + Py_ssize_t start, + Py_ssize_t end); +#endif // Py_BUILD_CORE diff --git a/include/context.h b/include/cpython/context.h similarity index 99% rename from include/context.h rename to include/cpython/context.h index 4e500708..4db079f7 100644 --- a/include/context.h +++ b/include/cpython/context.h @@ -1,12 +1,10 @@ +#ifndef Py_LIMITED_API #ifndef Py_CONTEXT_H #define Py_CONTEXT_H #ifdef __cplusplus extern "C" { #endif -#ifndef Py_LIMITED_API - - PyAPI_DATA(PyTypeObject) PyContext_Type; typedef struct _pycontextobject PyContext; @@ -73,9 +71,8 @@ PyAPI_FUNC(int) PyContextVar_Reset(PyObject *var, PyObject *token); PyAPI_FUNC(PyObject *) _PyContext_NewHamtForTests(void); -#endif /* !Py_LIMITED_API */ - #ifdef __cplusplus } #endif #endif /* !Py_CONTEXT_H */ +#endif /* !Py_LIMITED_API */ diff --git a/include/cpython/descrobject.h b/include/cpython/descrobject.h new file mode 100644 index 00000000..e2ea1b9a --- /dev/null +++ b/include/cpython/descrobject.h @@ -0,0 +1,64 @@ +#ifndef Py_CPYTHON_DESCROBJECT_H +# error "this header file must not be included directly" +#endif + +typedef PyObject *(*wrapperfunc)(PyObject *self, PyObject *args, + void *wrapped); + +typedef PyObject *(*wrapperfunc_kwds)(PyObject *self, PyObject *args, + void *wrapped, PyObject *kwds); + +struct wrapperbase { + const char *name; + int offset; + void *function; + wrapperfunc wrapper; + const char *doc; + int flags; + PyObject *name_strobj; +}; + +/* Flags for above struct */ +#define PyWrapperFlag_KEYWORDS 1 /* wrapper function takes keyword args */ + +/* Various kinds of descriptor objects */ + +typedef struct { + PyObject_HEAD + PyTypeObject *d_type; + PyObject *d_name; + PyObject *d_qualname; +} PyDescrObject; + +#define PyDescr_COMMON PyDescrObject d_common + +#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type) +#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name) + +typedef struct { + PyDescr_COMMON; + PyMethodDef *d_method; + vectorcallfunc vectorcall; +} PyMethodDescrObject; + +typedef struct { + PyDescr_COMMON; + PyMemberDef *d_member; +} PyMemberDescrObject; + +typedef struct { + PyDescr_COMMON; + PyGetSetDef *d_getset; +} PyGetSetDescrObject; + +typedef struct { + PyDescr_COMMON; + struct wrapperbase *d_base; + void *d_wrapped; /* This can be any function pointer */ +} PyWrapperDescrObject; + +PyAPI_DATA(PyTypeObject) _PyMethodWrapper_Type; + +PyAPI_FUNC(PyObject *) PyDescr_NewWrapper(PyTypeObject *, + struct wrapperbase *, void *); +PyAPI_FUNC(int) PyDescr_IsData(PyObject *); diff --git a/include/cpython/dictobject.h b/include/cpython/dictobject.h index 641d7bdc..033eaeb4 100644 --- a/include/cpython/dictobject.h +++ b/include/cpython/dictobject.h @@ -3,6 +3,7 @@ #endif typedef struct _dictkeysobject PyDictKeysObject; +typedef struct _dictvalues PyDictValues; /* The ma_values pointer is NULL for a combined table * or points to an array of PyObject* for a split table @@ -24,13 +25,14 @@ typedef struct { If ma_values is not NULL, the table is split: keys are stored in ma_keys and values are stored in ma_values */ - PyObject **ma_values; + PyDictValues *ma_values; } PyDictObject; PyAPI_FUNC(PyObject *) _PyDict_GetItem_KnownHash(PyObject *mp, PyObject *key, Py_hash_t hash); +PyAPI_FUNC(PyObject *) _PyDict_GetItemWithError(PyObject *dp, PyObject *key); PyAPI_FUNC(PyObject *) _PyDict_GetItemIdWithError(PyObject *dp, - struct _Py_Identifier *key); + _Py_Identifier *key); PyAPI_FUNC(PyObject *) _PyDict_GetItemStringWithError(PyObject *, const char *); PyAPI_FUNC(PyObject *) PyDict_SetDefault( PyObject *mp, PyObject *key, PyObject *defaultobj); @@ -40,22 +42,18 @@ PyAPI_FUNC(int) _PyDict_DelItem_KnownHash(PyObject *mp, PyObject *key, Py_hash_t hash); PyAPI_FUNC(int) _PyDict_DelItemIf(PyObject *mp, PyObject *key, int (*predicate)(PyObject *value)); -PyDictKeysObject *_PyDict_NewKeysForClass(void); PyAPI_FUNC(int) _PyDict_Next( PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, Py_hash_t *hash); /* Get the number of items of a dictionary. */ #define PyDict_GET_SIZE(mp) (assert(PyDict_Check(mp)),((PyDictObject *)mp)->ma_used) PyAPI_FUNC(int) _PyDict_Contains_KnownHash(PyObject *, PyObject *, Py_hash_t); -PyAPI_FUNC(int) _PyDict_ContainsId(PyObject *, struct _Py_Identifier *); +PyAPI_FUNC(int) _PyDict_ContainsId(PyObject *, _Py_Identifier *); PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused); PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp); PyAPI_FUNC(int) _PyDict_HasOnlyStringKeys(PyObject *mp); -Py_ssize_t _PyDict_KeysSize(PyDictKeysObject *keys); PyAPI_FUNC(Py_ssize_t) _PyDict_SizeOf(PyDictObject *); PyAPI_FUNC(PyObject *) _PyDict_Pop(PyObject *, PyObject *, PyObject *); -PyObject *_PyDict_Pop_KnownHash(PyObject *, PyObject *, Py_hash_t, PyObject *); -PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *); #define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL) /* Like PyDict_Merge, but override can be 0, 1 or 2. If override is 0, @@ -64,15 +62,11 @@ PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *); argument is raised. */ PyAPI_FUNC(int) _PyDict_MergeEx(PyObject *mp, PyObject *other, int override); -PyAPI_FUNC(int) _PyDict_SetItemId(PyObject *dp, struct _Py_Identifier *key, PyObject *item); +PyAPI_FUNC(int) _PyDict_SetItemId(PyObject *dp, _Py_Identifier *key, PyObject *item); -PyAPI_FUNC(int) _PyDict_DelItemId(PyObject *mp, struct _Py_Identifier *key); +PyAPI_FUNC(int) _PyDict_DelItemId(PyObject *mp, _Py_Identifier *key); PyAPI_FUNC(void) _PyDict_DebugMallocStats(FILE *out); -int _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr, PyObject *name, PyObject *value); -PyObject *_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObject *); -Py_ssize_t _PyDict_GetItemHint(PyDictObject *, PyObject *, Py_ssize_t, PyObject **); - /* _PyDictView */ typedef struct { diff --git a/include/cpython/fileutils.h b/include/cpython/fileutils.h index ccf37e94..b386ad10 100644 --- a/include/cpython/fileutils.h +++ b/include/cpython/fileutils.h @@ -2,171 +2,7 @@ # error "this header file must not be included directly" #endif -typedef enum { - _Py_ERROR_UNKNOWN=0, - _Py_ERROR_STRICT, - _Py_ERROR_SURROGATEESCAPE, - _Py_ERROR_REPLACE, - _Py_ERROR_IGNORE, - _Py_ERROR_BACKSLASHREPLACE, - _Py_ERROR_SURROGATEPASS, - _Py_ERROR_XMLCHARREFREPLACE, - _Py_ERROR_OTHER -} _Py_error_handler; - -PyAPI_FUNC(_Py_error_handler) _Py_GetErrorHandler(const char *errors); - -PyAPI_FUNC(int) _Py_DecodeLocaleEx( - const char *arg, - wchar_t **wstr, - size_t *wlen, - const char **reason, - int current_locale, - _Py_error_handler errors); - -PyAPI_FUNC(int) _Py_EncodeLocaleEx( - const wchar_t *text, - char **str, - size_t *error_pos, - const char **reason, - int current_locale, - _Py_error_handler errors); - -PyAPI_FUNC(char*) _Py_EncodeLocaleRaw( - const wchar_t *text, - size_t *error_pos); - -PyAPI_FUNC(PyObject *) _Py_device_encoding(int); - -#if defined(MS_WINDOWS) || defined(__APPLE__) - /* On Windows, the count parameter of read() is an int (bpo-9015, bpo-9611). - On macOS 10.13, read() and write() with more than INT_MAX bytes - fail with EINVAL (bpo-24658). */ -# define _PY_READ_MAX INT_MAX -# define _PY_WRITE_MAX INT_MAX -#else - /* write() should truncate the input to PY_SSIZE_T_MAX bytes, - but it's safer to do it ourself to have a portable behaviour */ -# define _PY_READ_MAX PY_SSIZE_T_MAX -# define _PY_WRITE_MAX PY_SSIZE_T_MAX -#endif - -#ifdef MS_WINDOWS -struct _Py_stat_struct { - unsigned long st_dev; - uint64_t st_ino; - unsigned short st_mode; - int st_nlink; - int st_uid; - int st_gid; - unsigned long st_rdev; - __int64 st_size; - time_t st_atime; - int st_atime_nsec; - time_t st_mtime; - int st_mtime_nsec; - time_t st_ctime; - int st_ctime_nsec; - unsigned long st_file_attributes; - unsigned long st_reparse_tag; -}; -#else -# define _Py_stat_struct stat -#endif - -PyAPI_FUNC(int) _Py_fstat( - int fd, - struct _Py_stat_struct *status); - -PyAPI_FUNC(int) _Py_fstat_noraise( - int fd, - struct _Py_stat_struct *status); - -PyAPI_FUNC(int) _Py_stat( - PyObject *path, - struct stat *status); - -PyAPI_FUNC(int) _Py_open( - const char *pathname, - int flags); - -PyAPI_FUNC(int) _Py_open_noraise( - const char *pathname, - int flags); - -PyAPI_FUNC(FILE *) _Py_wfopen( - const wchar_t *path, - const wchar_t *mode); - +// Used by _testcapi which must not use the internal C API PyAPI_FUNC(FILE*) _Py_fopen_obj( PyObject *path, const char *mode); - -PyAPI_FUNC(Py_ssize_t) _Py_read( - int fd, - void *buf, - size_t count); - -PyAPI_FUNC(Py_ssize_t) _Py_write( - int fd, - const void *buf, - size_t count); - -PyAPI_FUNC(Py_ssize_t) _Py_write_noraise( - int fd, - const void *buf, - size_t count); - -#ifdef HAVE_READLINK -PyAPI_FUNC(int) _Py_wreadlink( - const wchar_t *path, - wchar_t *buf, - /* Number of characters of 'buf' buffer - including the trailing NUL character */ - size_t buflen); -#endif - -#ifdef HAVE_REALPATH -PyAPI_FUNC(wchar_t*) _Py_wrealpath( - const wchar_t *path, - wchar_t *resolved_path, - /* Number of characters of 'resolved_path' buffer - including the trailing NUL character */ - size_t resolved_path_len); -#endif - -#ifndef MS_WINDOWS -PyAPI_FUNC(int) _Py_isabs(const wchar_t *path); -#endif - -PyAPI_FUNC(int) _Py_abspath(const wchar_t *path, wchar_t **abspath_p); - -PyAPI_FUNC(wchar_t*) _Py_wgetcwd( - wchar_t *buf, - /* Number of characters of 'buf' buffer - including the trailing NUL character */ - size_t buflen); - -PyAPI_FUNC(int) _Py_get_inheritable(int fd); - -PyAPI_FUNC(int) _Py_set_inheritable(int fd, int inheritable, - int *atomic_flag_works); - -PyAPI_FUNC(int) _Py_set_inheritable_async_safe(int fd, int inheritable, - int *atomic_flag_works); - -PyAPI_FUNC(int) _Py_dup(int fd); - -#ifndef MS_WINDOWS -PyAPI_FUNC(int) _Py_get_blocking(int fd); - -PyAPI_FUNC(int) _Py_set_blocking(int fd, int blocking); -#else /* MS_WINDOWS */ -PyAPI_FUNC(void*) _Py_get_osfhandle_noraise(int fd); - -PyAPI_FUNC(void*) _Py_get_osfhandle(int fd); - -PyAPI_FUNC(int) _Py_open_osfhandle_noraise(void *handle, int flags); - -PyAPI_FUNC(int) _Py_open_osfhandle(void *handle, int flags); -#endif /* MS_WINDOWS */ diff --git a/include/cpython/floatobject.h b/include/cpython/floatobject.h new file mode 100644 index 00000000..7795d9f8 --- /dev/null +++ b/include/cpython/floatobject.h @@ -0,0 +1,21 @@ +#ifndef Py_CPYTHON_FLOATOBJECT_H +# error "this header file must not be included directly" +#endif + +typedef struct { + PyObject_HEAD + double ob_fval; +} PyFloatObject; + +// Macro version of PyFloat_AsDouble() trading safety for speed. +// It doesn't check if op is a double object. +#define PyFloat_AS_DOUBLE(op) (((PyFloatObject *)(op))->ob_fval) + + +PyAPI_FUNC(int) PyFloat_Pack2(double x, char *p, int le); +PyAPI_FUNC(int) PyFloat_Pack4(double x, char *p, int le); +PyAPI_FUNC(int) PyFloat_Pack8(double x, char *p, int le); + +PyAPI_FUNC(double) PyFloat_Unpack2(const char *p, int le); +PyAPI_FUNC(double) PyFloat_Unpack4(const char *p, int le); +PyAPI_FUNC(double) PyFloat_Unpack8(const char *p, int le); diff --git a/include/cpython/frameobject.h b/include/cpython/frameobject.h index 5122ec41..4e19535c 100644 --- a/include/cpython/frameobject.h +++ b/include/cpython/frameobject.h @@ -4,91 +4,26 @@ # error "this header file must not be included directly" #endif -/* These values are chosen so that the inline functions below all - * compare f_state to zero. - */ -enum _framestate { - FRAME_CREATED = -2, - FRAME_SUSPENDED = -1, - FRAME_EXECUTING = 0, - FRAME_RETURNED = 1, - FRAME_UNWINDING = 2, - FRAME_RAISED = 3, - FRAME_CLEARED = 4 -}; - -typedef signed char PyFrameState; - -typedef struct { - int b_type; /* what kind of block this is */ - int b_handler; /* where to jump to find handler */ - int b_level; /* value stack level to pop to */ -} PyTryBlock; - -struct _frame { - PyObject_VAR_HEAD - struct _frame *f_back; /* previous frame, or NULL */ - PyCodeObject *f_code; /* code segment */ - PyObject *f_builtins; /* builtin symbol table (PyDictObject) */ - PyObject *f_globals; /* global symbol table (PyDictObject) */ - PyObject *f_locals; /* local symbol table (any mapping) */ - PyObject **f_valuestack; /* points after the last local */ - PyObject *f_trace; /* Trace function */ - int f_stackdepth; /* Depth of value stack */ - char f_trace_lines; /* Emit per-line trace events? */ - char f_trace_opcodes; /* Emit per-opcode trace events? */ - - /* Borrowed reference to a generator, or NULL */ - PyObject *f_gen; - - int f_lasti; /* Last instruction if called */ - int f_lineno; /* Current line number. Only valid if non-zero */ - int f_iblock; /* index in f_blockstack */ - PyFrameState f_state; /* What state the frame is in */ - PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */ - PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */ -}; - -static inline int _PyFrame_IsRunnable(struct _frame *f) { - return f->f_state < FRAME_EXECUTING; -} - -static inline int _PyFrame_IsExecuting(struct _frame *f) { - return f->f_state == FRAME_EXECUTING; -} - -static inline int _PyFrameHasCompleted(struct _frame *f) { - return f->f_state > FRAME_EXECUTING; -} - /* Standard object interface */ -PyAPI_DATA(PyTypeObject) PyFrame_Type; - -#define PyFrame_Check(op) Py_IS_TYPE(op, &PyFrame_Type) - PyAPI_FUNC(PyFrameObject *) PyFrame_New(PyThreadState *, PyCodeObject *, PyObject *, PyObject *); -/* only internal use */ -PyFrameObject* -_PyFrame_New_NoTrack(PyThreadState *, PyFrameConstructor *, PyObject *); - - /* The rest of the interface is specific for frame objects */ -/* Block management functions */ - -PyAPI_FUNC(void) PyFrame_BlockSetup(PyFrameObject *, int, int, int); -PyAPI_FUNC(PyTryBlock *) PyFrame_BlockPop(PyFrameObject *); - /* Conversions between "fast locals" and locals in dictionary */ PyAPI_FUNC(void) PyFrame_LocalsToFast(PyFrameObject *, int); -PyAPI_FUNC(int) PyFrame_FastToLocalsWithError(PyFrameObject *f); -PyAPI_FUNC(void) PyFrame_FastToLocals(PyFrameObject *); +/* -- Caveat emptor -- + * The concept of entry frames is an implementation detail of the CPython + * interpreter. This API is considered unstable and is provided for the + * convenience of debuggers, profilers and state-inspecting tools. Notice that + * this API can be changed in future minor versions if the underlying frame + * mechanism change or the concept of an 'entry frame' or its semantics becomes + * obsolete or outdated. */ -PyAPI_FUNC(void) _PyFrame_DebugMallocStats(FILE *out); +PyAPI_FUNC(int) _PyFrame_IsEntryFrame(PyFrameObject *frame); -PyAPI_FUNC(PyFrameObject *) PyFrame_GetBack(PyFrameObject *frame); +PyAPI_FUNC(int) PyFrame_FastToLocalsWithError(PyFrameObject *f); +PyAPI_FUNC(void) PyFrame_FastToLocals(PyFrameObject *); diff --git a/include/funcobject.h b/include/cpython/funcobject.h similarity index 92% rename from include/funcobject.h rename to include/cpython/funcobject.h index d7acd18c..99ac6008 100644 --- a/include/funcobject.h +++ b/include/cpython/funcobject.h @@ -1,5 +1,5 @@ - /* Function object interface */ + #ifndef Py_LIMITED_API #ifndef Py_FUNCOBJECT_H #define Py_FUNCOBJECT_H @@ -42,6 +42,14 @@ typedef struct { PyObject *func_module; /* The __module__ attribute, can be anything */ PyObject *func_annotations; /* Annotations, a dict or NULL */ vectorcallfunc vectorcall; + /* Version number for use by specializer. + * Can set to non-zero when we want to specialize. + * Will be set to zero if any of these change: + * defaults + * kwdefaults (only if the object changes, not the contents of the dict) + * code + * annotations */ + uint32_t func_version; /* Invariant: * func_closure contains the bindings for func_code->co_freevars, so @@ -68,13 +76,11 @@ PyAPI_FUNC(int) PyFunction_SetClosure(PyObject *, PyObject *); PyAPI_FUNC(PyObject *) PyFunction_GetAnnotations(PyObject *); PyAPI_FUNC(int) PyFunction_SetAnnotations(PyObject *, PyObject *); -#ifndef Py_LIMITED_API PyAPI_FUNC(PyObject *) _PyFunction_Vectorcall( PyObject *func, PyObject *const *stack, size_t nargsf, PyObject *kwnames); -#endif /* Macros for direct access to these values. Type checks are *not* done, so use with care. */ @@ -93,9 +99,6 @@ PyAPI_FUNC(PyObject *) _PyFunction_Vectorcall( #define PyFunction_GET_ANNOTATIONS(func) \ (((PyFunctionObject *)func) -> func_annotations) -#define PyFunction_AS_FRAME_CONSTRUCTOR(func) \ - ((PyFrameConstructor *)&((PyFunctionObject *)(func))->func_globals) - /* The classmethod and staticmethod types lives here, too */ PyAPI_DATA(PyTypeObject) PyClassMethod_Type; PyAPI_DATA(PyTypeObject) PyStaticMethod_Type; diff --git a/include/genobject.h b/include/cpython/genobject.h similarity index 72% rename from include/genobject.h rename to include/cpython/genobject.h index e965334a..40eaa19d 100644 --- a/include/genobject.h +++ b/include/cpython/genobject.h @@ -1,4 +1,3 @@ - /* Generator object interface */ #ifndef Py_LIMITED_API @@ -8,24 +7,28 @@ extern "C" { #endif -#include "pystate.h" /* _PyErr_StackItem */ -#include "abstract.h" /* PySendResult */ +/* --- Generators --------------------------------------------------------- */ /* _PyGenObject_HEAD defines the initial segment of generator and coroutine objects. */ #define _PyGenObject_HEAD(prefix) \ PyObject_HEAD \ - /* Note: gi_frame can be NULL if the generator is "finished" */ \ - PyFrameObject *prefix##_frame; \ /* The code object backing the generator */ \ - PyObject *prefix##_code; \ + PyCodeObject *prefix##_code; \ /* List of weak reference. */ \ PyObject *prefix##_weakreflist; \ /* Name of the generator. */ \ PyObject *prefix##_name; \ /* Qualified name of the generator. */ \ PyObject *prefix##_qualname; \ - _PyErr_StackItem prefix##_exc_state; + _PyErr_StackItem prefix##_exc_state; \ + PyObject *prefix##_origin_or_finalizer; \ + char prefix##_hooks_inited; \ + char prefix##_closed; \ + char prefix##_running_async; \ + /* The frame */ \ + int8_t prefix##_frame_state; \ + PyObject *prefix##_iframe[1]; typedef struct { /* The gi_ prefix is intended to remind of generator-iterator. */ @@ -42,39 +45,27 @@ PyAPI_FUNC(PyObject *) PyGen_NewWithQualName(PyFrameObject *, PyObject *name, PyObject *qualname); PyAPI_FUNC(int) _PyGen_SetStopIterationValue(PyObject *); PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **); -PyObject *_PyGen_yf(PyGenObject *); PyAPI_FUNC(void) _PyGen_Finalize(PyObject *self); -#ifndef Py_LIMITED_API + +/* --- PyCoroObject ------------------------------------------------------- */ + typedef struct { _PyGenObject_HEAD(cr) - PyObject *cr_origin; } PyCoroObject; PyAPI_DATA(PyTypeObject) PyCoro_Type; PyAPI_DATA(PyTypeObject) _PyCoroWrapper_Type; #define PyCoro_CheckExact(op) Py_IS_TYPE(op, &PyCoro_Type) -PyObject *_PyCoro_GetAwaitableIter(PyObject *o); PyAPI_FUNC(PyObject *) PyCoro_New(PyFrameObject *, PyObject *name, PyObject *qualname); -/* Asynchronous Generators */ + +/* --- Asynchronous Generators -------------------------------------------- */ typedef struct { _PyGenObject_HEAD(ag) - PyObject *ag_finalizer; - - /* Flag is set to 1 when hooks set up by sys.set_asyncgen_hooks - were called on the generator, to avoid calling them more - than once. */ - int ag_hooks_inited; - - /* Flag is set to 1 when aclose() is called for the first time, or - when a StopAsyncIteration exception is raised. */ - int ag_closed; - - int ag_running_async; } PyAsyncGenObject; PyAPI_DATA(PyTypeObject) PyAsyncGen_Type; @@ -87,9 +78,6 @@ PyAPI_FUNC(PyObject *) PyAsyncGen_New(PyFrameObject *, #define PyAsyncGen_CheckExact(op) Py_IS_TYPE(op, &PyAsyncGen_Type) -PyObject *_PyAsyncGenValueWrapperNew(PyObject *); - -#endif #undef _PyGenObject_HEAD diff --git a/include/cpython/import.h b/include/cpython/import.h index 419945f7..a69b4f34 100644 --- a/include/cpython/import.h +++ b/include/cpython/import.h @@ -6,16 +6,13 @@ PyMODINIT_FUNC PyInit__imp(void); PyAPI_FUNC(int) _PyImport_IsInitialized(PyInterpreterState *); -PyAPI_FUNC(PyObject *) _PyImport_GetModuleId(struct _Py_Identifier *name); +PyAPI_FUNC(PyObject *) _PyImport_GetModuleId(_Py_Identifier *name); PyAPI_FUNC(int) _PyImport_SetModule(PyObject *name, PyObject *module); PyAPI_FUNC(int) _PyImport_SetModuleString(const char *name, PyObject* module); PyAPI_FUNC(void) _PyImport_AcquireLock(void); PyAPI_FUNC(int) _PyImport_ReleaseLock(void); -/* Obsolete since 3.5, will be removed in 3.11. */ -Py_DEPRECATED(3.10) PyAPI_FUNC(PyObject *) _PyImport_FindExtensionObject(PyObject *, PyObject *); - PyAPI_FUNC(int) _PyImport_FixupBuiltin( PyObject *mod, const char *name, /* UTF-8 encoded string */ @@ -35,6 +32,8 @@ struct _frozen { const char *name; /* ASCII encoded string */ const unsigned char *code; int size; + int is_package; + PyObject *(*get_code)(void); }; /* Embedding apps may change this pointer to point to their favorite diff --git a/include/cpython/initconfig.h b/include/cpython/initconfig.h index 583165be..3b6d5938 100644 --- a/include/cpython/initconfig.h +++ b/include/cpython/initconfig.h @@ -143,8 +143,10 @@ typedef struct PyConfig { int faulthandler; int tracemalloc; int import_time; + int code_debug_ranges; int show_ref_count; int dump_refs; + wchar_t *dump_refs_file; int malloc_stats; wchar_t *filesystem_encoding; wchar_t *filesystem_errors; @@ -173,6 +175,8 @@ typedef struct PyConfig { int legacy_windows_stdio; #endif wchar_t *check_hash_pycs_mode; + int use_frozen_modules; + int safe_path; /* --- Path configuration inputs ------------ */ int pathconfig_warnings; @@ -184,6 +188,7 @@ typedef struct PyConfig { /* --- Path configuration outputs ----------- */ int module_search_paths_set; PyWideStringList module_search_paths; + wchar_t *stdlib_dir; wchar_t *executable; wchar_t *base_executable; wchar_t *prefix; @@ -209,6 +214,9 @@ typedef struct PyConfig { // If non-zero, disallow threads, subprocesses, and fork. // Default: 0. int _isolated_interpreter; + + // If non-zero, we believe we're running from a source tree. + int _is_python_build; } PyConfig; PyAPI_FUNC(void) PyConfig_InitPythonConfig(PyConfig *config); diff --git a/include/cpython/listobject.h b/include/cpython/listobject.h index e3239152..1add8213 100644 --- a/include/cpython/listobject.h +++ b/include/cpython/listobject.h @@ -24,11 +24,28 @@ typedef struct { PyAPI_FUNC(PyObject *) _PyList_Extend(PyListObject *, PyObject *); PyAPI_FUNC(void) _PyList_DebugMallocStats(FILE *out); -/* Macro, trading safety for speed */ - /* Cast argument to PyListObject* type. */ -#define _PyList_CAST(op) (assert(PyList_Check(op)), (PyListObject *)(op)) +#define _PyList_CAST(op) \ + (assert(PyList_Check(op)), _Py_CAST(PyListObject*, (op))) + +// Macros and static inline functions, trading safety for speed + +static inline Py_ssize_t PyList_GET_SIZE(PyObject *op) { + PyListObject *list = _PyList_CAST(op); + return Py_SIZE(list); +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyList_GET_SIZE(op) PyList_GET_SIZE(_PyObject_CAST(op)) +#endif + +#define PyList_GET_ITEM(op, index) (_PyList_CAST(op)->ob_item[index]) -#define PyList_GET_ITEM(op, i) (_PyList_CAST(op)->ob_item[i]) -#define PyList_SET_ITEM(op, i, v) ((void)(_PyList_CAST(op)->ob_item[i] = (v))) -#define PyList_GET_SIZE(op) Py_SIZE(_PyList_CAST(op)) +static inline void +PyList_SET_ITEM(PyObject *op, Py_ssize_t index, PyObject *value) { + PyListObject *list = _PyList_CAST(op); + list->ob_item[index] = value; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +#define PyList_SET_ITEM(op, index, value) \ + PyList_SET_ITEM(_PyObject_CAST(op), index, _PyObject_CAST(value)) +#endif diff --git a/include/longintrepr.h b/include/cpython/longintrepr.h similarity index 95% rename from include/longintrepr.h rename to include/cpython/longintrepr.h index ff4155f9..68dbf9c4 100644 --- a/include/longintrepr.h +++ b/include/cpython/longintrepr.h @@ -21,8 +21,6 @@ extern "C" { PyLong_SHIFT. The majority of the code doesn't care about the precise value of PyLong_SHIFT, but there are some notable exceptions: - - long_pow() requires that PyLong_SHIFT be divisible by 5 - - PyLong_{As,From}ByteArray require that PyLong_SHIFT be at least 8 - long_hash() requires that PyLong_SHIFT is *strictly* less than the number @@ -63,10 +61,6 @@ typedef long stwodigits; /* signed variant of twodigits */ #define PyLong_BASE ((digit)1 << PyLong_SHIFT) #define PyLong_MASK ((digit)(PyLong_BASE - 1)) -#if PyLong_SHIFT % 5 != 0 -#error "longobject.c requires that PyLong_SHIFT be divisible by 5" -#endif - /* Long integer representation. The absolute value of a number is equal to SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i) diff --git a/include/cpython/longobject.h b/include/cpython/longobject.h new file mode 100644 index 00000000..1a73799d --- /dev/null +++ b/include/cpython/longobject.h @@ -0,0 +1,95 @@ +#ifndef Py_CPYTHON_LONGOBJECT_H +# error "this header file must not be included directly" +#endif + +PyAPI_FUNC(int) _PyLong_AsInt(PyObject *); + +PyAPI_FUNC(int) _PyLong_UnsignedShort_Converter(PyObject *, void *); +PyAPI_FUNC(int) _PyLong_UnsignedInt_Converter(PyObject *, void *); +PyAPI_FUNC(int) _PyLong_UnsignedLong_Converter(PyObject *, void *); +PyAPI_FUNC(int) _PyLong_UnsignedLongLong_Converter(PyObject *, void *); +PyAPI_FUNC(int) _PyLong_Size_t_Converter(PyObject *, void *); + +/* _PyLong_Frexp returns a double x and an exponent e such that the + true value is approximately equal to x * 2**e. e is >= 0. x is + 0.0 if and only if the input is 0 (in which case, e and x are both + zeroes); otherwise, 0.5 <= abs(x) < 1.0. On overflow, which is + possible if the number of bits doesn't fit into a Py_ssize_t, sets + OverflowError and returns -1.0 for x, 0 for e. */ +PyAPI_FUNC(double) _PyLong_Frexp(PyLongObject *a, Py_ssize_t *e); + +PyAPI_FUNC(PyObject *) PyLong_FromUnicodeObject(PyObject *u, int base); +PyAPI_FUNC(PyObject *) _PyLong_FromBytes(const char *, Py_ssize_t, int); + +/* _PyLong_Sign. Return 0 if v is 0, -1 if v < 0, +1 if v > 0. + v must not be NULL, and must be a normalized long. + There are no error cases. +*/ +PyAPI_FUNC(int) _PyLong_Sign(PyObject *v); + +/* _PyLong_NumBits. Return the number of bits needed to represent the + absolute value of a long. For example, this returns 1 for 1 and -1, 2 + for 2 and -2, and 2 for 3 and -3. It returns 0 for 0. + v must not be NULL, and must be a normalized long. + (size_t)-1 is returned and OverflowError set if the true result doesn't + fit in a size_t. +*/ +PyAPI_FUNC(size_t) _PyLong_NumBits(PyObject *v); + +/* _PyLong_DivmodNear. Given integers a and b, compute the nearest + integer q to the exact quotient a / b, rounding to the nearest even integer + in the case of a tie. Return (q, r), where r = a - q*b. The remainder r + will satisfy abs(r) <= abs(b)/2, with equality possible only if q is + even. +*/ +PyAPI_FUNC(PyObject *) _PyLong_DivmodNear(PyObject *, PyObject *); + +/* _PyLong_FromByteArray: View the n unsigned bytes as a binary integer in + base 256, and return a Python int with the same numeric value. + If n is 0, the integer is 0. Else: + If little_endian is 1/true, bytes[n-1] is the MSB and bytes[0] the LSB; + else (little_endian is 0/false) bytes[0] is the MSB and bytes[n-1] the + LSB. + If is_signed is 0/false, view the bytes as a non-negative integer. + If is_signed is 1/true, view the bytes as a 2's-complement integer, + non-negative if bit 0x80 of the MSB is clear, negative if set. + Error returns: + + Return NULL with the appropriate exception set if there's not + enough memory to create the Python int. +*/ +PyAPI_FUNC(PyObject *) _PyLong_FromByteArray( + const unsigned char* bytes, size_t n, + int little_endian, int is_signed); + +/* _PyLong_AsByteArray: Convert the least-significant 8*n bits of long + v to a base-256 integer, stored in array bytes. Normally return 0, + return -1 on error. + If little_endian is 1/true, store the MSB at bytes[n-1] and the LSB at + bytes[0]; else (little_endian is 0/false) store the MSB at bytes[0] and + the LSB at bytes[n-1]. + If is_signed is 0/false, it's an error if v < 0; else (v >= 0) n bytes + are filled and there's nothing special about bit 0x80 of the MSB. + If is_signed is 1/true, bytes is filled with the 2's-complement + representation of v's value. Bit 0x80 of the MSB is the sign bit. + Error returns (-1): + + is_signed is 0 and v < 0. TypeError is set in this case, and bytes + isn't altered. + + n isn't big enough to hold the full mathematical value of v. For + example, if is_signed is 0 and there are more digits in the v than + fit in n; or if is_signed is 1, v < 0, and n is just 1 bit shy of + being large enough to hold a sign bit. OverflowError is set in this + case, but bytes holds the least-significant n bytes of the true value. +*/ +PyAPI_FUNC(int) _PyLong_AsByteArray(PyLongObject* v, + unsigned char* bytes, size_t n, + int little_endian, int is_signed); + +/* _PyLong_Format: Convert the long to a string object with given base, + appending a base prefix of 0[box] if base is 2, 8 or 16. */ +PyAPI_FUNC(PyObject *) _PyLong_Format(PyObject *obj, int base); + +/* For use by the gcd function in mathmodule.c */ +PyAPI_FUNC(PyObject *) _PyLong_GCD(PyObject *, PyObject *); + +PyAPI_FUNC(PyObject *) _PyLong_Rshift(PyObject *, size_t); +PyAPI_FUNC(PyObject *) _PyLong_Lshift(PyObject *, size_t); diff --git a/include/cpython/methodobject.h b/include/cpython/methodobject.h index 7ecbfe3b..54a61cfd 100644 --- a/include/cpython/methodobject.h +++ b/include/cpython/methodobject.h @@ -2,23 +2,7 @@ # error "this header file must not be included directly" #endif -PyAPI_DATA(PyTypeObject) PyCMethod_Type; - -#define PyCMethod_CheckExact(op) Py_IS_TYPE(op, &PyCMethod_Type) -#define PyCMethod_Check(op) PyObject_TypeCheck(op, &PyCMethod_Type) - -/* Macros for direct access to these values. Type checks are *not* - done, so use with care. */ -#define PyCFunction_GET_FUNCTION(func) \ - (((PyCFunctionObject *)func) -> m_ml -> ml_meth) -#define PyCFunction_GET_SELF(func) \ - (((PyCFunctionObject *)func) -> m_ml -> ml_flags & METH_STATIC ? \ - NULL : ((PyCFunctionObject *)func) -> m_self) -#define PyCFunction_GET_FLAGS(func) \ - (((PyCFunctionObject *)func) -> m_ml -> ml_flags) -#define PyCFunction_GET_CLASS(func) \ - (((PyCFunctionObject *)func) -> m_ml -> ml_flags & METH_METHOD ? \ - ((PyCMethodObject *)func) -> mm_class : NULL) +// PyCFunctionObject structure typedef struct { PyObject_HEAD @@ -29,7 +13,62 @@ typedef struct { vectorcallfunc vectorcall; } PyCFunctionObject; +#define _PyCFunctionObject_CAST(func) \ + (assert(PyCFunction_Check(func)), \ + _Py_CAST(PyCFunctionObject*, (func))) + + +// PyCMethodObject structure + typedef struct { PyCFunctionObject func; PyTypeObject *mm_class; /* Class that defines this method */ } PyCMethodObject; + +#define _PyCMethodObject_CAST(func) \ + (assert(PyCMethod_Check(func)), \ + _Py_CAST(PyCMethodObject*, (func))) + +PyAPI_DATA(PyTypeObject) PyCMethod_Type; + +#define PyCMethod_CheckExact(op) Py_IS_TYPE(op, &PyCMethod_Type) +#define PyCMethod_Check(op) PyObject_TypeCheck(op, &PyCMethod_Type) + + +/* Static inline functions for direct access to these values. + Type checks are *not* done, so use with care. */ +static inline PyCFunction PyCFunction_GET_FUNCTION(PyObject *func) { + return _PyCFunctionObject_CAST(func)->m_ml->ml_meth; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyCFunction_GET_FUNCTION(func) PyCFunction_GET_FUNCTION(_PyObject_CAST(func)) +#endif + +static inline PyObject* PyCFunction_GET_SELF(PyObject *func_obj) { + PyCFunctionObject *func = _PyCFunctionObject_CAST(func_obj); + if (func->m_ml->ml_flags & METH_STATIC) { + return _Py_NULL; + } + return func->m_self; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyCFunction_GET_SELF(func) PyCFunction_GET_SELF(_PyObject_CAST(func)) +#endif + +static inline int PyCFunction_GET_FLAGS(PyObject *func) { + return _PyCFunctionObject_CAST(func)->m_ml->ml_flags; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyCFunction_GET_FLAGS(func) PyCFunction_GET_FLAGS(_PyObject_CAST(func)) +#endif + +static inline PyTypeObject* PyCFunction_GET_CLASS(PyObject *func_obj) { + PyCFunctionObject *func = _PyCFunctionObject_CAST(func_obj); + if (func->m_ml->ml_flags & METH_METHOD) { + return _PyCMethodObject_CAST(func)->mm_class; + } + return _Py_NULL; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyCFunction_GET_CLASS(func) PyCFunction_GET_CLASS(_PyObject_CAST(func)) +#endif diff --git a/include/cpython/modsupport.h b/include/cpython/modsupport.h new file mode 100644 index 00000000..769eb52b --- /dev/null +++ b/include/cpython/modsupport.h @@ -0,0 +1,107 @@ +#ifndef Py_CPYTHON_MODSUPPORT_H +# error "this header file must not be included directly" +#endif + +/* If PY_SSIZE_T_CLEAN is defined, each functions treats #-specifier + to mean Py_ssize_t */ +#ifdef PY_SSIZE_T_CLEAN +#define _Py_VaBuildStack _Py_VaBuildStack_SizeT +#else +PyAPI_FUNC(PyObject *) _Py_VaBuildValue_SizeT(const char *, va_list); +PyAPI_FUNC(PyObject **) _Py_VaBuildStack_SizeT( + PyObject **small_stack, + Py_ssize_t small_stack_len, + const char *format, + va_list va, + Py_ssize_t *p_nargs); +#endif + +PyAPI_FUNC(int) _PyArg_UnpackStack( + PyObject *const *args, + Py_ssize_t nargs, + const char *name, + Py_ssize_t min, + Py_ssize_t max, + ...); + +PyAPI_FUNC(int) _PyArg_NoKeywords(const char *funcname, PyObject *kwargs); +PyAPI_FUNC(int) _PyArg_NoKwnames(const char *funcname, PyObject *kwnames); +PyAPI_FUNC(int) _PyArg_NoPositional(const char *funcname, PyObject *args); +#define _PyArg_NoKeywords(funcname, kwargs) \ + ((kwargs) == NULL || _PyArg_NoKeywords((funcname), (kwargs))) +#define _PyArg_NoKwnames(funcname, kwnames) \ + ((kwnames) == NULL || _PyArg_NoKwnames((funcname), (kwnames))) +#define _PyArg_NoPositional(funcname, args) \ + ((args) == NULL || _PyArg_NoPositional((funcname), (args))) + +PyAPI_FUNC(void) _PyArg_BadArgument(const char *, const char *, const char *, PyObject *); +PyAPI_FUNC(int) _PyArg_CheckPositional(const char *, Py_ssize_t, + Py_ssize_t, Py_ssize_t); +#define _PyArg_CheckPositional(funcname, nargs, min, max) \ + ((!ANY_VARARGS(max) && (min) <= (nargs) && (nargs) <= (max)) \ + || _PyArg_CheckPositional((funcname), (nargs), (min), (max))) + +PyAPI_FUNC(PyObject **) _Py_VaBuildStack( + PyObject **small_stack, + Py_ssize_t small_stack_len, + const char *format, + va_list va, + Py_ssize_t *p_nargs); + +typedef struct _PyArg_Parser { + const char *format; + const char * const *keywords; + const char *fname; + const char *custom_msg; + int pos; /* number of positional-only arguments */ + int min; /* minimal number of arguments */ + int max; /* maximal number of positional arguments */ + PyObject *kwtuple; /* tuple of keyword parameter names */ + struct _PyArg_Parser *next; +} _PyArg_Parser; + +#ifdef PY_SSIZE_T_CLEAN +#define _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT +#define _PyArg_ParseStack _PyArg_ParseStack_SizeT +#define _PyArg_ParseStackAndKeywords _PyArg_ParseStackAndKeywords_SizeT +#define _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT +#endif + +PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *, + struct _PyArg_Parser *, ...); +PyAPI_FUNC(int) _PyArg_ParseStack( + PyObject *const *args, + Py_ssize_t nargs, + const char *format, + ...); +PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords( + PyObject *const *args, + Py_ssize_t nargs, + PyObject *kwnames, + struct _PyArg_Parser *, + ...); +PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *, + struct _PyArg_Parser *, va_list); +PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywords( + PyObject *const *args, Py_ssize_t nargs, + PyObject *kwargs, PyObject *kwnames, + struct _PyArg_Parser *parser, + int minpos, int maxpos, int minkw, + PyObject **buf); + +PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywordsWithVararg( + PyObject *const *args, Py_ssize_t nargs, + PyObject *kwargs, PyObject *kwnames, + struct _PyArg_Parser *parser, + int minpos, int maxpos, int minkw, + int vararg, PyObject **buf); + +#define _PyArg_UnpackKeywords(args, nargs, kwargs, kwnames, parser, minpos, maxpos, minkw, buf) \ + (((minkw) == 0 && (kwargs) == NULL && (kwnames) == NULL && \ + (minpos) <= (nargs) && (nargs) <= (maxpos) && args != NULL) ? (args) : \ + _PyArg_UnpackKeywords((args), (nargs), (kwargs), (kwnames), (parser), \ + (minpos), (maxpos), (minkw), (buf))) + +PyAPI_FUNC(PyObject *) _PyModule_CreateInitialized(PyModuleDef*, int apiver); + +PyAPI_DATA(const char *) _Py_PackageContext; diff --git a/include/cpython/object.h b/include/cpython/object.h index 84c60e55..b018dabf 100644 --- a/include/cpython/object.h +++ b/include/cpython/object.h @@ -41,25 +41,15 @@ typedef struct _Py_Identifier { Py_ssize_t index; } _Py_Identifier; +#if defined(NEEDS_PY_IDENTIFIER) || !defined(Py_BUILD_CORE) +// For now we are keeping _Py_IDENTIFIER for continued use +// in non-builtin extensions (and naughty PyPI modules). + #define _Py_static_string_init(value) { .string = value, .index = -1 } #define _Py_static_string(varname, value) static _Py_Identifier varname = _Py_static_string_init(value) #define _Py_IDENTIFIER(varname) _Py_static_string(PyId_##varname, #varname) -/* buffer interface */ -typedef struct bufferinfo { - void *buf; - PyObject *obj; /* owned reference */ - Py_ssize_t len; - Py_ssize_t itemsize; /* This is Py_ssize_t so it can be - pointed to by strides in simple case.*/ - int readonly; - int ndim; - char *format; - Py_ssize_t *shape; - Py_ssize_t *strides; - Py_ssize_t *suboffsets; - void *internal; -} Py_buffer; +#endif /* NEEDS_PY_IDENTIFIER */ typedef int (*getbufferproc)(PyObject *, Py_buffer *, int); typedef void (*releasebufferproc)(PyObject *, Py_buffer *); @@ -67,39 +57,6 @@ typedef void (*releasebufferproc)(PyObject *, Py_buffer *); typedef PyObject *(*vectorcallfunc)(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames); -/* Maximum number of dimensions */ -#define PyBUF_MAX_NDIM 64 - -/* Flags for getting buffers */ -#define PyBUF_SIMPLE 0 -#define PyBUF_WRITABLE 0x0001 -/* we used to include an E, backwards compatible alias */ -#define PyBUF_WRITEABLE PyBUF_WRITABLE -#define PyBUF_FORMAT 0x0004 -#define PyBUF_ND 0x0008 -#define PyBUF_STRIDES (0x0010 | PyBUF_ND) -#define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES) -#define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES) -#define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES) -#define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES) - -#define PyBUF_CONTIG (PyBUF_ND | PyBUF_WRITABLE) -#define PyBUF_CONTIG_RO (PyBUF_ND) - -#define PyBUF_STRIDED (PyBUF_STRIDES | PyBUF_WRITABLE) -#define PyBUF_STRIDED_RO (PyBUF_STRIDES) - -#define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT) -#define PyBUF_RECORDS_RO (PyBUF_STRIDES | PyBUF_FORMAT) - -#define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT) -#define PyBUF_FULL_RO (PyBUF_INDIRECT | PyBUF_FORMAT) - - -#define PyBUF_READ 0x100 -#define PyBUF_WRITE 0x200 -/* End buffer interface */ - typedef struct { /* Number implementations must check *both* @@ -244,11 +201,11 @@ struct _typeobject { iternextfunc tp_iternext; /* Attribute descriptor and subclassing stuff */ - struct PyMethodDef *tp_methods; - struct PyMemberDef *tp_members; - struct PyGetSetDef *tp_getset; + PyMethodDef *tp_methods; + PyMemberDef *tp_members; + PyGetSetDef *tp_getset; // Strong reference on a heap type, borrowed reference on a static type - struct _typeobject *tp_base; + PyTypeObject *tp_base; PyObject *tp_dict; descrgetfunc tp_descr_get; descrsetfunc tp_descr_set; @@ -272,6 +229,13 @@ struct _typeobject { vectorcallfunc tp_vectorcall; }; +/* This struct is used by the specializer + * It should should be treated as an opaque blob + * by code other than the specializer and interpreter. */ +struct _specialization_cache { + PyObject *getitem; +}; + /* The *real* layout of a type object when allocated on the heap */ typedef struct _heaptypeobject { /* Note: there's a dependency on the order of these members @@ -289,32 +253,33 @@ typedef struct _heaptypeobject { PyObject *ht_name, *ht_slots, *ht_qualname; struct _dictkeysobject *ht_cached_keys; PyObject *ht_module; + char *_ht_tpname; // Storage for "tp_name"; see PyType_FromModuleAndSpec + struct _specialization_cache _spec_cache; // For use by the specializer. /* here are optional user slots, followed by the members. */ } PyHeapTypeObject; -/* access macro to the members which are floating "behind" the object */ -#define PyHeapType_GET_MEMBERS(etype) \ - ((PyMemberDef *)(((char *)etype) + Py_TYPE(etype)->tp_basicsize)) - PyAPI_FUNC(const char *) _PyType_Name(PyTypeObject *); PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *); PyAPI_FUNC(PyObject *) _PyType_LookupId(PyTypeObject *, _Py_Identifier *); -PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, _Py_Identifier *); +PyAPI_FUNC(PyObject *) _PyObject_LookupSpecialId(PyObject *, _Py_Identifier *); +#ifndef Py_BUILD_CORE +// Backward compatibility for 3rd-party extensions +// that may be using the old name. +#define _PyObject_LookupSpecial _PyObject_LookupSpecialId +#endif PyAPI_FUNC(PyTypeObject *) _PyType_CalculateMetaclass(PyTypeObject *, PyObject *); PyAPI_FUNC(PyObject *) _PyType_GetDocFromInternalDoc(const char *, const char *); PyAPI_FUNC(PyObject *) _PyType_GetTextSignatureFromInternalDoc(const char *, const char *); -struct PyModuleDef; -PyAPI_FUNC(PyObject *) _PyType_GetModuleByDef(PyTypeObject *, struct PyModuleDef *); +PyAPI_FUNC(PyObject *) PyType_GetModuleByDef(PyTypeObject *, PyModuleDef *); -struct _Py_Identifier; PyAPI_FUNC(int) PyObject_Print(PyObject *, FILE *, int); PyAPI_FUNC(void) _Py_BreakPoint(void); PyAPI_FUNC(void) _PyObject_Dump(PyObject *); PyAPI_FUNC(int) _PyObject_IsFreed(PyObject *); PyAPI_FUNC(int) _PyObject_IsAbstract(PyObject *); -PyAPI_FUNC(PyObject *) _PyObject_GetAttrId(PyObject *, struct _Py_Identifier *); -PyAPI_FUNC(int) _PyObject_SetAttrId(PyObject *, struct _Py_Identifier *, PyObject *); +PyAPI_FUNC(PyObject *) _PyObject_GetAttrId(PyObject *, _Py_Identifier *); +PyAPI_FUNC(int) _PyObject_SetAttrId(PyObject *, _Py_Identifier *, PyObject *); /* Replacements of PyObject_GetAttr() and _PyObject_GetAttrId() which don't raise AttributeError. @@ -325,7 +290,7 @@ PyAPI_FUNC(int) _PyObject_SetAttrId(PyObject *, struct _Py_Identifier *, PyObjec is raised. */ PyAPI_FUNC(int) _PyObject_LookupAttr(PyObject *, PyObject *, PyObject **); -PyAPI_FUNC(int) _PyObject_LookupAttrId(PyObject *, struct _Py_Identifier *, PyObject **); +PyAPI_FUNC(int) _PyObject_LookupAttrId(PyObject *, _Py_Identifier *, PyObject **); PyAPI_FUNC(int) _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method); @@ -493,8 +458,8 @@ without deallocating anything (and so unbounded call-stack depth is avoided). When the call stack finishes unwinding again, code generated by the END macro notices this, and calls another routine to deallocate all the objects that may have been added to the list of deferred deallocations. In effect, a -chain of N deallocations is broken into (N-1)/(PyTrash_UNWIND_LEVEL-1) pieces, -with the call stack never exceeding a depth of PyTrash_UNWIND_LEVEL. +chain of N deallocations is broken into (N-1)/(_PyTrash_UNWIND_LEVEL-1) pieces, +with the call stack never exceeding a depth of _PyTrash_UNWIND_LEVEL. Since the tp_dealloc of a subclass typically calls the tp_dealloc of the base class, we need to ensure that the trashcan is only triggered on the tp_dealloc @@ -503,27 +468,12 @@ partially-deallocated object. To check this, the tp_dealloc function must be passed as second argument to Py_TRASHCAN_BEGIN(). */ -/* This is the old private API, invoked by the macros before 3.2.4. - Kept for binary compatibility of extensions using the stable ABI. */ -PyAPI_FUNC(void) _PyTrash_deposit_object(PyObject*); -PyAPI_FUNC(void) _PyTrash_destroy_chain(void); - -/* This is the old private API, invoked by the macros before 3.9. - Kept for binary compatibility of extensions using the stable ABI. */ -PyAPI_FUNC(void) _PyTrash_thread_deposit_object(PyObject*); -PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(void); - -/* Forward declarations for PyThreadState */ -struct _ts; - /* Python 3.9 private API, invoked by the macros below. */ -PyAPI_FUNC(int) _PyTrash_begin(struct _ts *tstate, PyObject *op); -PyAPI_FUNC(void) _PyTrash_end(struct _ts *tstate); +PyAPI_FUNC(int) _PyTrash_begin(PyThreadState *tstate, PyObject *op); +PyAPI_FUNC(void) _PyTrash_end(PyThreadState *tstate); /* Python 3.10 private API, invoked by the Py_TRASHCAN_BEGIN(). */ PyAPI_FUNC(int) _PyTrash_cond(PyObject *op, destructor dealloc); -#define PyTrash_UNWIND_LEVEL 50 - #define Py_TRASHCAN_BEGIN_CONDITION(op, cond) \ do { \ PyThreadState *_tstate = NULL; \ @@ -546,7 +496,16 @@ PyAPI_FUNC(int) _PyTrash_cond(PyObject *op, destructor dealloc); Py_TRASHCAN_BEGIN_CONDITION(op, \ _PyTrash_cond(_PyObject_CAST(op), (destructor)dealloc)) -/* For backwards compatibility, these macros enable the trashcan - * unconditionally */ -#define Py_TRASHCAN_SAFE_BEGIN(op) Py_TRASHCAN_BEGIN_CONDITION(op, 1) -#define Py_TRASHCAN_SAFE_END(op) Py_TRASHCAN_END +/* The following two macros, Py_TRASHCAN_SAFE_BEGIN and + * Py_TRASHCAN_SAFE_END, are deprecated since version 3.11 and + * will be removed in the future. + * Use Py_TRASHCAN_BEGIN and Py_TRASHCAN_END instead. + */ +Py_DEPRECATED(3.11) typedef int UsingDeprecatedTrashcanMacro; +#define Py_TRASHCAN_SAFE_BEGIN(op) \ + do { \ + UsingDeprecatedTrashcanMacro cond=1; \ + Py_TRASHCAN_BEGIN_CONDITION(op, cond); +#define Py_TRASHCAN_SAFE_END(op) \ + Py_TRASHCAN_END; \ + } while(0); diff --git a/include/cpython/objimpl.h b/include/cpython/objimpl.h index d83700e2..d7c76eab 100644 --- a/include/cpython/objimpl.h +++ b/include/cpython/objimpl.h @@ -52,14 +52,6 @@ the 1st step is performed automatically for you, so in a C++ class constructor you would start directly with PyObject_Init/InitVar. */ -/* This function returns the number of allocated memory blocks, regardless of size */ -PyAPI_FUNC(Py_ssize_t) _Py_GetAllocatedBlocks(void); - -/* Macros */ -#ifdef WITH_PYMALLOC -PyAPI_FUNC(int) _PyObject_DebugMallocStats(FILE *out); -#endif - typedef struct { /* user context passed as the first argument to the 2 functions */ @@ -90,11 +82,8 @@ PyAPI_FUNC(int) PyObject_IS_GC(PyObject *obj); # define _PyGC_FINALIZED(o) PyObject_GC_IsFinalized(o) #endif -PyAPI_FUNC(PyObject *) _PyObject_GC_Malloc(size_t size); -PyAPI_FUNC(PyObject *) _PyObject_GC_Calloc(size_t size); - -/* Test if a type supports weak references */ -#define PyType_SUPPORTS_WEAKREFS(t) ((t)->tp_weaklistoffset > 0) +// Test if a type supports weak references +PyAPI_FUNC(int) PyType_SUPPORTS_WEAKREFS(PyTypeObject *type); PyAPI_FUNC(PyObject **) PyObject_GET_WEAKREFS_LISTPTR(PyObject *op); diff --git a/include/cpython/pthread_stubs.h b/include/cpython/pthread_stubs.h new file mode 100644 index 00000000..d95ee03d --- /dev/null +++ b/include/cpython/pthread_stubs.h @@ -0,0 +1,88 @@ +#ifndef Py_CPYTHON_PTRHEAD_STUBS_H +#define Py_CPYTHON_PTRHEAD_STUBS_H + +#if !defined(HAVE_PTHREAD_STUBS) +# error "this header file requires stubbed pthreads." +#endif + +#ifndef _POSIX_THREADS +# define _POSIX_THREADS 1 +#endif + +/* Minimal pthread stubs for CPython. + * + * The stubs implement the minimum pthread API for CPython. + * - pthread_create() fails. + * - pthread_exit() calls exit(0). + * - pthread_key_*() functions implement minimal TSS without destructor. + * - all other functions do nothing and return 0. + */ + +#ifdef __wasi__ +// WASI's bits/alltypes.h provides type definitions when __NEED_ is set. +// The header file can be included multiple times. +# define __NEED_pthread_cond_t 1 +# define __NEED_pthread_condattr_t 1 +# define __NEED_pthread_mutex_t 1 +# define __NEED_pthread_mutexattr_t 1 +# define __NEED_pthread_key_t 1 +# define __NEED_pthread_t 1 +# define __NEED_pthread_attr_t 1 +# include +#else +typedef struct { void *__x; } pthread_cond_t; +typedef struct { unsigned __attr; } pthread_condattr_t; +typedef struct { void *__x; } pthread_mutex_t; +typedef struct { unsigned __attr; } pthread_mutexattr_t; +typedef unsigned pthread_key_t; +typedef unsigned pthread_t; +typedef struct { unsigned __attr; } pthread_attr_t; +#endif + +// mutex +PyAPI_FUNC(int) pthread_mutex_init(pthread_mutex_t *restrict mutex, + const pthread_mutexattr_t *restrict attr); +PyAPI_FUNC(int) pthread_mutex_destroy(pthread_mutex_t *mutex); +PyAPI_FUNC(int) pthread_mutex_trylock(pthread_mutex_t *mutex); +PyAPI_FUNC(int) pthread_mutex_lock(pthread_mutex_t *mutex); +PyAPI_FUNC(int) pthread_mutex_unlock(pthread_mutex_t *mutex); + +// condition +PyAPI_FUNC(int) pthread_cond_init(pthread_cond_t *restrict cond, + const pthread_condattr_t *restrict attr); +PyAPI_FUNC(int) pthread_cond_destroy(pthread_cond_t *cond); +PyAPI_FUNC(int) pthread_cond_wait(pthread_cond_t *restrict cond, + pthread_mutex_t *restrict mutex); +PyAPI_FUNC(int) pthread_cond_timedwait(pthread_cond_t *restrict cond, + pthread_mutex_t *restrict mutex, + const struct timespec *restrict abstime); +PyAPI_FUNC(int) pthread_cond_signal(pthread_cond_t *cond); +PyAPI_FUNC(int) pthread_condattr_init(pthread_condattr_t *attr); +PyAPI_FUNC(int) pthread_condattr_setclock( + pthread_condattr_t *attr, clockid_t clock_id); + +// pthread +PyAPI_FUNC(int) pthread_create(pthread_t *restrict thread, + const pthread_attr_t *restrict attr, + void *(*start_routine)(void *), + void *restrict arg); +PyAPI_FUNC(int) pthread_detach(pthread_t thread); +PyAPI_FUNC(pthread_t) pthread_self(void); +PyAPI_FUNC(int) pthread_exit(void *retval) __attribute__ ((__noreturn__)); +PyAPI_FUNC(int) pthread_attr_init(pthread_attr_t *attr); +PyAPI_FUNC(int) pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); +PyAPI_FUNC(int) pthread_attr_destroy(pthread_attr_t *attr); + + +// pthread_key +#ifndef PTHREAD_KEYS_MAX +# define PTHREAD_KEYS_MAX 128 +#endif + +PyAPI_FUNC(int) pthread_key_create(pthread_key_t *key, + void (*destr_function)(void *)); +PyAPI_FUNC(int) pthread_key_delete(pthread_key_t key); +PyAPI_FUNC(void *) pthread_getspecific(pthread_key_t key); +PyAPI_FUNC(int) pthread_setspecific(pthread_key_t key, const void *value); + +#endif // Py_CPYTHON_PTRHEAD_STUBS_H diff --git a/include/cpython/pydebug.h b/include/cpython/pydebug.h index 78bcb118..cab799f0 100644 --- a/include/cpython/pydebug.h +++ b/include/cpython/pydebug.h @@ -29,7 +29,7 @@ PyAPI_DATA(int) Py_LegacyWindowsStdioFlag; /* this is a wrapper around getenv() that pays attention to Py_IgnoreEnvironmentFlag. It should be used for getting variables like PYTHONPATH and PYTHONHOME from the environment */ -#define Py_GETENV(s) (Py_IgnoreEnvironmentFlag ? NULL : getenv(s)) +PyAPI_DATA(char*) Py_GETENV(const char *name); #ifdef __cplusplus } diff --git a/include/cpython/pyerrors.h b/include/cpython/pyerrors.h index 3f952456..47d80e32 100644 --- a/include/cpython/pyerrors.h +++ b/include/cpython/pyerrors.h @@ -6,7 +6,7 @@ /* PyException_HEAD defines the initial segment of every exception class. */ #define PyException_HEAD PyObject_HEAD PyObject *dict;\ - PyObject *args; PyObject *traceback;\ + PyObject *args; PyObject *notes; PyObject *traceback;\ PyObject *context; PyObject *cause;\ char suppress_context; @@ -14,6 +14,12 @@ typedef struct { PyException_HEAD } PyBaseExceptionObject; +typedef struct { + PyException_HEAD + PyObject *msg; + PyObject *excs; +} PyBaseExceptionGroupObject; + typedef struct { PyException_HEAD PyObject *msg; @@ -85,20 +91,14 @@ typedef PyOSErrorObject PyWindowsErrorObject; PyAPI_FUNC(void) _PyErr_SetKeyError(PyObject *); PyAPI_FUNC(_PyErr_StackItem*) _PyErr_GetTopmostException(PyThreadState *tstate); +PyAPI_FUNC(PyObject*) _PyErr_GetHandledException(PyThreadState *); +PyAPI_FUNC(void) _PyErr_SetHandledException(PyThreadState *, PyObject *); PyAPI_FUNC(void) _PyErr_GetExcInfo(PyThreadState *, PyObject **, PyObject **, PyObject **); /* Context manipulation (PEP 3134) */ PyAPI_FUNC(void) _PyErr_ChainExceptions(PyObject *, PyObject *, PyObject *); -/* Convenience functions */ - -#ifdef MS_WINDOWS -Py_DEPRECATED(3.3) -PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithUnicodeFilename( - PyObject *, const Py_UNICODE *); -#endif /* MS_WINDOWS */ - /* Like PyErr_Format(), but saves current exception as __context__ and __cause__. */ @@ -108,16 +108,6 @@ PyAPI_FUNC(PyObject *) _PyErr_FormatFromCause( ... ); -#ifdef MS_WINDOWS -/* XXX redeclare to use WSTRING */ -Py_DEPRECATED(3.3) -PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithUnicodeFilename( - int, const Py_UNICODE *); -Py_DEPRECATED(3.3) -PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithUnicodeFilename( - PyObject *,int, const Py_UNICODE *); -#endif - /* In exceptions.c */ /* Helper that attempts to replace the current exception with one of the @@ -161,31 +151,6 @@ PyAPI_FUNC(PyObject *) PyErr_ProgramTextObject( PyObject *filename, int lineno); -/* Create a UnicodeEncodeError object. - * - * TODO: This API will be removed in Python 3.11. - */ -Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject *) PyUnicodeEncodeError_Create( - const char *encoding, /* UTF-8 encoded string */ - const Py_UNICODE *object, - Py_ssize_t length, - Py_ssize_t start, - Py_ssize_t end, - const char *reason /* UTF-8 encoded string */ - ); - -/* Create a UnicodeTranslateError object. - * - * TODO: This API will be removed in Python 3.11. - */ -Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject *) PyUnicodeTranslateError_Create( - const Py_UNICODE *object, - Py_ssize_t length, - Py_ssize_t start, - Py_ssize_t end, - const char *reason /* UTF-8 encoded string */ - ); - PyAPI_FUNC(PyObject *) _PyErr_ProgramDecodedTextObject( PyObject *filename, int lineno, diff --git a/include/cpython/pyframe.h b/include/cpython/pyframe.h new file mode 100644 index 00000000..1dc634cc --- /dev/null +++ b/include/cpython/pyframe.h @@ -0,0 +1,17 @@ +#ifndef Py_CPYTHON_PYFRAME_H +# error "this header file must not be included directly" +#endif + +PyAPI_DATA(PyTypeObject) PyFrame_Type; + +#define PyFrame_Check(op) Py_IS_TYPE((op), &PyFrame_Type) + +PyAPI_FUNC(PyFrameObject *) PyFrame_GetBack(PyFrameObject *frame); +PyAPI_FUNC(PyObject *) PyFrame_GetLocals(PyFrameObject *frame); + +PyAPI_FUNC(PyObject *) PyFrame_GetGlobals(PyFrameObject *frame); +PyAPI_FUNC(PyObject *) PyFrame_GetBuiltins(PyFrameObject *frame); + +PyAPI_FUNC(PyObject *) PyFrame_GetGenerator(PyFrameObject *frame); +PyAPI_FUNC(int) PyFrame_GetLasti(PyFrameObject *frame); + diff --git a/include/cpython/pylifecycle.h b/include/cpython/pylifecycle.h index 5faeb353..bb5b07ef 100644 --- a/include/cpython/pylifecycle.h +++ b/include/cpython/pylifecycle.h @@ -9,8 +9,9 @@ PyAPI_FUNC(int) Py_FrozenMain(int argc, char **argv); /* Only used by applications that embed the interpreter and need to * override the standard encoding determination mechanism */ -PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding, - const char *errors); +Py_DEPRECATED(3.11) PyAPI_FUNC(int) Py_SetStandardStreamEncoding( + const char *encoding, + const char *errors); /* PEP 432 Multi-phase initialization API (Private while provisional!) */ @@ -45,7 +46,7 @@ PyAPI_FUNC(void) _Py_RestoreSignals(void); PyAPI_FUNC(int) Py_FdIsInteractive(FILE *, const char *); PyAPI_FUNC(int) _Py_FdIsInteractive(FILE *fp, PyObject *filename); -PyAPI_FUNC(void) _Py_SetProgramFullPath(const wchar_t *); +Py_DEPRECATED(3.11) PyAPI_FUNC(void) _Py_SetProgramFullPath(const wchar_t *); PyAPI_FUNC(const char *) _Py_gitidentifier(void); PyAPI_FUNC(const char *) _Py_gitversion(void); diff --git a/include/cpython/pystate.h b/include/cpython/pystate.h index 7c995b93..2bd46067 100644 --- a/include/cpython/pystate.h +++ b/include/cpython/pystate.h @@ -2,6 +2,7 @@ # error "this header file must not be included directly" #endif + PyAPI_FUNC(int) _PyInterpreterState_RequiresIDRef(PyInterpreterState *); PyAPI_FUNC(void) _PyInterpreterState_RequireIDRef(PyInterpreterState *, int); @@ -27,7 +28,14 @@ typedef int (*Py_tracefunc)(PyObject *, PyFrameObject *, int, PyObject *); #define PyTrace_OPCODE 7 -typedef struct _cframe { +typedef struct { + PyCodeObject *code; // The code object for the bounds. May be NULL. + PyCodeAddressRange bounds; // Only valid if code != NULL. +} PyTraceInfo; + +// Internal structure: you should not use it directly, but use public functions +// like PyThreadState_EnterTracing() and PyThreadState_LeaveTracing(). +typedef struct _PyCFrame { /* This struct will be threaded through the C stack * allowing fast access to per-thread state that needs * to be accessed quickly by the interpreter, but can @@ -38,46 +46,68 @@ typedef struct _cframe { * discipline and make sure that instances of this struct cannot * accessed outside of their lifetime. */ - int use_tracing; - struct _cframe *previous; -} CFrame; + uint8_t use_tracing; // 0 or 255 (or'ed into opcode, hence 8-bit type) + /* Pointer to the currently executing frame (it can be NULL) */ + struct _PyInterpreterFrame *current_frame; + struct _PyCFrame *previous; +} _PyCFrame; typedef struct _err_stackitem { - /* This struct represents an entry on the exception stack, which is a - * per-coroutine state. (Coroutine in the computer science sense, - * including the thread and generators). - * This ensures that the exception state is not impacted by "yields" - * from an except handler. + /* This struct represents a single execution context where we might + * be currently handling an exception. It is a per-coroutine state + * (coroutine in the computer science sense, including the thread + * and generators). + * + * This is used as an entry on the exception stack, where each + * entry indicates if it is currently handling an exception. + * This ensures that the exception state is not impacted + * by "yields" from an except handler. The thread + * always has an entry (the bottom-most one). */ - PyObject *exc_type, *exc_value, *exc_traceback; + + /* The exception currently being handled in this context, if any. */ + PyObject *exc_value; struct _err_stackitem *previous_item; } _PyErr_StackItem; +typedef struct _stack_chunk { + struct _stack_chunk *previous; + size_t size; + size_t top; + PyObject * data[1]; /* Variable sized */ +} _PyStackChunk; -// The PyThreadState typedef is in Include/pystate.h. struct _ts { /* See Python/ceval.c for comments explaining most fields */ - struct _ts *prev; - struct _ts *next; + PyThreadState *prev; + PyThreadState *next; PyInterpreterState *interp; - /* Borrowed reference to the current frame (it can be NULL) */ - PyFrameObject *frame; - int recursion_depth; + /* Has been initialized to a safe state. + + In order to be effective, this must be set to 0 during or right + after allocation. */ + int _initialized; + + /* Was this thread state statically allocated? */ + int _static; + + int recursion_remaining; + int recursion_limit; int recursion_headroom; /* Allow 50 more calls to handle any errors. */ - int stackcheck_counter; /* 'tracing' keeps track of the execution depth when tracing/profiling. This is to prevent the actual trace/profile code from being recorded in the trace/profile. */ int tracing; + int tracing_what; /* The event currently being traced, if any. */ - /* Pointer to current CFrame in the C stack frame of the currently, + /* Pointer to current _PyCFrame in the C stack frame of the currently, * or most recently, executing _PyEval_EvalFrameDefault. */ - CFrame *cframe; + _PyCFrame *cframe; Py_tracefunc c_profilefunc; Py_tracefunc c_tracefunc; @@ -89,13 +119,9 @@ struct _ts { PyObject *curexc_value; PyObject *curexc_traceback; - /* The exception currently being handled, if no coroutines/generators - * are present. Always last element on the stack referred to be exc_info. - */ - _PyErr_StackItem exc_state; - - /* Pointer to the top of the stack of the exceptions currently - * being handled */ + /* Pointer to the top of the exception stack for the exceptions + * we may be currently handling. (See _PyErr_StackItem above.) + * This is never NULL. */ _PyErr_StackItem *exc_info; PyObject *dict; /* Stores per-thread state */ @@ -105,6 +131,12 @@ struct _ts { PyObject *async_exc; /* Asynchronous exception to raise */ unsigned long thread_id; /* Thread id where this tstate was created */ + /* Native thread id where this tstate was created. This will be 0 except on + * those platforms that have the notion of native thread id, for which the + * macro PY_HAVE_THREAD_NATIVE_ID is then defined. + */ + unsigned long native_thread_id; + int trash_delete_nesting; PyObject *trash_delete_later; @@ -145,12 +177,34 @@ struct _ts { /* Unique thread state id. */ uint64_t id; - CFrame root_cframe; + PyTraceInfo trace_info; + _PyStackChunk *datastack_chunk; + PyObject **datastack_top; + PyObject **datastack_limit; /* XXX signal handlers should also be here */ + /* The following fields are here to avoid allocation during init. + The data is exposed through PyThreadState pointer fields. + These fields should not be accessed directly outside of init. + This is indicated by an underscore prefix on the field names. + + All other PyInterpreterState pointer fields are populated when + needed and default to NULL. + */ + // Note some fields do not have a leading underscore for backward + // compatibility. See https://bugs.python.org/issue45953#msg412046. + + /* The thread's exception stack entry. (Always the last entry.) */ + _PyErr_StackItem exc_state; + + /* The bottom-most frame on the stack. */ + _PyCFrame root_cframe; }; + +/* other API */ + // Alias for backward compatibility with Python 3.8 #define _PyInterpreterState_Get PyInterpreterState_Get @@ -162,6 +216,13 @@ PyAPI_FUNC(PyThreadState *) _PyThreadState_UncheckedGet(void); PyAPI_FUNC(PyObject *) _PyThreadState_GetDict(PyThreadState *tstate); +// Disable tracing and profiling. +PyAPI_FUNC(void) PyThreadState_EnterTracing(PyThreadState *tstate); + +// Reset tracing and profiling: enable them if a trace function or a profile +// function is set, otherwise disable them. +PyAPI_FUNC(void) PyThreadState_LeaveTracing(PyThreadState *tstate); + /* PyGILState */ /* Helper/diagnostic function - return 1 if the current thread @@ -200,7 +261,7 @@ PyAPI_FUNC(void) PyThreadState_DeleteCurrent(void); /* Frame evaluation API */ -typedef PyObject* (*_PyFrameEvalFunction)(PyThreadState *tstate, PyFrameObject *, int); +typedef PyObject* (*_PyFrameEvalFunction)(PyThreadState *tstate, struct _PyInterpreterFrame *, int); PyAPI_FUNC(_PyFrameEvalFunction) _PyInterpreterState_GetEvalFrameFunc( PyInterpreterState *interp); @@ -247,12 +308,12 @@ PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void); /* cross-interpreter data */ -struct _xid; - // _PyCrossInterpreterData is similar to Py_buffer as an effectively // opaque struct that holds data outside the object machinery. This // is necessary to pass safely between interpreters in the same process. -typedef struct _xid { +typedef struct _xid _PyCrossInterpreterData; + +struct _xid { // data is the cross-interpreter-safe derivation of a Python object // (see _PyObject_GetCrossInterpreterData). It will be NULL if the // new_object func (below) encodes the data. @@ -278,7 +339,7 @@ typedef struct _xid { // interpreter given the data. The resulting object (a new // reference) will be equivalent to the original object. This field // is required. - PyObject *(*new_object)(struct _xid *); + PyObject *(*new_object)(_PyCrossInterpreterData *); // free is called when the data is released. If it is NULL then // nothing will be done to free the data. For some types this is // okay (e.g. bytes) and for those types this field should be set @@ -289,7 +350,7 @@ typedef struct _xid { // to PyMem_RawFree (the default if not explicitly set to NULL). // The call will happen with the original interpreter activated. void (*free)(void *); -} _PyCrossInterpreterData; +}; PyAPI_FUNC(int) _PyObject_GetCrossInterpreterData(PyObject *, _PyCrossInterpreterData *); PyAPI_FUNC(PyObject *) _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *); @@ -299,7 +360,7 @@ PyAPI_FUNC(int) _PyObject_CheckCrossInterpreterData(PyObject *); /* cross-interpreter data registry */ -typedef int (*crossinterpdatafunc)(PyObject *, struct _xid *); +typedef int (*crossinterpdatafunc)(PyObject *, _PyCrossInterpreterData *); PyAPI_FUNC(int) _PyCrossInterpreterData_RegisterClass(PyTypeObject *, crossinterpdatafunc); PyAPI_FUNC(crossinterpdatafunc) _PyCrossInterpreterData_Lookup(PyObject *); diff --git a/include/cpython/pythread.h b/include/cpython/pythread.h new file mode 100644 index 00000000..ce4ec8f6 --- /dev/null +++ b/include/cpython/pythread.h @@ -0,0 +1,42 @@ +#ifndef Py_CPYTHON_PYTHREAD_H +# error "this header file must not be included directly" +#endif + +#define PYTHREAD_INVALID_THREAD_ID ((unsigned long)-1) + +#ifdef HAVE_FORK +/* Private function to reinitialize a lock at fork in the child process. + Reset the lock to the unlocked state. + Return 0 on success, return -1 on error. */ +PyAPI_FUNC(int) _PyThread_at_fork_reinit(PyThread_type_lock *lock); +#endif /* HAVE_FORK */ + +#ifdef HAVE_PTHREAD_H + /* Darwin needs pthread.h to know type name the pthread_key_t. */ +# include +# define NATIVE_TSS_KEY_T pthread_key_t +#elif defined(NT_THREADS) + /* In Windows, native TSS key type is DWORD, + but hardcode the unsigned long to avoid errors for include directive. + */ +# define NATIVE_TSS_KEY_T unsigned long +#elif defined(HAVE_PTHREAD_STUBS) +# include "cpython/pthread_stubs.h" +# define NATIVE_TSS_KEY_T pthread_key_t +#else +# error "Require native threads. See https://bugs.python.org/issue31370" +#endif + +/* When Py_LIMITED_API is not defined, the type layout of Py_tss_t is + exposed to allow static allocation in the API clients. Even in this case, + you must handle TSS keys through API functions due to compatibility. +*/ +struct _Py_tss_t { + int _is_initialized; + NATIVE_TSS_KEY_T _key; +}; + +#undef NATIVE_TSS_KEY_T + +/* When static allocation, you must initialize with Py_tss_NEEDS_INIT. */ +#define Py_tss_NEEDS_INIT {0} diff --git a/include/cpython/pytime.h b/include/cpython/pytime.h index 754c7f47..23d4f16a 100644 --- a/include/cpython/pytime.h +++ b/include/cpython/pytime.h @@ -1,3 +1,46 @@ +// The _PyTime_t API is written to use timestamp and timeout values stored in +// various formats and to read clocks. +// +// The _PyTime_t type is an integer to support directly common arithmetic +// operations like t1 + t2. +// +// The _PyTime_t API supports a resolution of 1 nanosecond. The _PyTime_t type +// is signed to support negative timestamps. The supported range is around +// [-292.3 years; +292.3 years]. Using the Unix epoch (January 1st, 1970), the +// supported date range is around [1677-09-21; 2262-04-11]. +// +// Formats: +// +// * seconds +// * seconds as a floating pointer number (C double) +// * milliseconds (10^-3 seconds) +// * microseconds (10^-6 seconds) +// * 100 nanoseconds (10^-7 seconds) +// * nanoseconds (10^-9 seconds) +// * timeval structure, 1 microsecond resolution (10^-6 seconds) +// * timespec structure, 1 nanosecond resolution (10^-9 seconds) +// +// Integer overflows are detected and raise OverflowError. Conversion to a +// resolution worse than 1 nanosecond is rounded correctly with the requested +// rounding mode. There are 4 rounding modes: floor (towards -inf), ceiling +// (towards +inf), half even and up (away from zero). +// +// Some functions clamp the result in the range [_PyTime_MIN; _PyTime_MAX], so +// the caller doesn't have to handle errors and doesn't need to hold the GIL. +// For example, _PyTime_Add(t1, t2) computes t1+t2 and clamp the result on +// overflow. +// +// Clocks: +// +// * System clock +// * Monotonic clock +// * Performance counter +// +// Operations like (t * k / q) with integers are implemented in a way to reduce +// the risk of integer overflow. Such operation is used to convert a clock +// value expressed in ticks with a frequency to _PyTime_t, like +// QueryPerformanceCounter() with QueryPerformanceFrequency(). + #ifndef Py_LIMITED_API #ifndef Py_PYTIME_H #define Py_PYTIME_H @@ -14,8 +57,11 @@ extern "C" { store a duration, and so indirectly a date (related to another date, like UNIX epoch). */ typedef int64_t _PyTime_t; +// _PyTime_MIN nanoseconds is around -292.3 years #define _PyTime_MIN INT64_MIN +// _PyTime_MAX nanoseconds is around +292.3 years #define _PyTime_MAX INT64_MAX +#define _SIZEOF_PYTIME_T 8 typedef enum { /* Round towards minus infinity (-inf). @@ -111,13 +157,24 @@ PyAPI_FUNC(_PyTime_t) _PyTime_AsMilliseconds(_PyTime_t t, PyAPI_FUNC(_PyTime_t) _PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round); +/* Convert timestamp to a number of nanoseconds (10^-9 seconds). */ +PyAPI_FUNC(_PyTime_t) _PyTime_AsNanoseconds(_PyTime_t t); + +#ifdef MS_WINDOWS +// Convert timestamp to a number of 100 nanoseconds (10^-7 seconds). +PyAPI_FUNC(_PyTime_t) _PyTime_As100Nanoseconds(_PyTime_t t, + _PyTime_round_t round); +#endif + /* Convert timestamp to a number of nanoseconds (10^-9 seconds) as a Python int object. */ PyAPI_FUNC(PyObject *) _PyTime_AsNanosecondsObject(_PyTime_t t); +#ifndef MS_WINDOWS /* Create a timestamp from a timeval structure. Raise an exception and return -1 on overflow, return 0 on success. */ PyAPI_FUNC(int) _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv); +#endif /* Convert a timestamp to a timeval structure (microsecond resolution). tv_usec is always positive. @@ -127,8 +184,9 @@ PyAPI_FUNC(int) _PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round); -/* Similar to _PyTime_AsTimeval(), but don't raise an exception on error. */ -PyAPI_FUNC(int) _PyTime_AsTimeval_noraise(_PyTime_t t, +/* Similar to _PyTime_AsTimeval() but don't raise an exception on overflow. + On overflow, clamp tv_sec to _PyTime_t min/max. */ +PyAPI_FUNC(void) _PyTime_AsTimeval_clamp(_PyTime_t t, struct timeval *tv, _PyTime_round_t round); @@ -153,9 +211,18 @@ PyAPI_FUNC(int) _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts); tv_nsec is always positive. Raise an exception and return -1 on error, return 0 on success. */ PyAPI_FUNC(int) _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts); + +/* Similar to _PyTime_AsTimespec() but don't raise an exception on overflow. + On overflow, clamp tv_sec to _PyTime_t min/max. */ +PyAPI_FUNC(void) _PyTime_AsTimespec_clamp(_PyTime_t t, struct timespec *ts); #endif + +// Compute t1 + t2. Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow. +PyAPI_FUNC(_PyTime_t) _PyTime_Add(_PyTime_t t1, _PyTime_t t2); + /* Compute ticks * mul / div. + Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow. The caller must ensure that ((div - 1) * mul) cannot overflow. */ PyAPI_FUNC(_PyTime_t) _PyTime_MulDiv(_PyTime_t ticks, _PyTime_t mul, @@ -172,8 +239,8 @@ typedef struct { /* Get the current time from the system clock. If the internal clock fails, silently ignore the error and return 0. - On integer overflow, silently ignore the overflow and truncated the clock to - _PyTime_MIN or _PyTime_MAX. + On integer overflow, silently ignore the overflow and clamp the clock to + [_PyTime_MIN; _PyTime_MAX]. Use _PyTime_GetSystemClockWithInfo() to check for failure. */ PyAPI_FUNC(_PyTime_t) _PyTime_GetSystemClock(void); @@ -192,8 +259,8 @@ PyAPI_FUNC(int) _PyTime_GetSystemClockWithInfo( results of consecutive calls is valid. If the internal clock fails, silently ignore the error and return 0. - On integer overflow, silently ignore the overflow and truncated the clock to - _PyTime_MIN or _PyTime_MAX. + On integer overflow, silently ignore the overflow and clamp the clock to + [_PyTime_MIN; _PyTime_MAX]. Use _PyTime_GetMonotonicClockWithInfo() to check for failure. */ PyAPI_FUNC(_PyTime_t) _PyTime_GetMonotonicClock(void); @@ -223,8 +290,8 @@ PyAPI_FUNC(int) _PyTime_gmtime(time_t t, struct tm *tm); measure a short duration. If the internal clock fails, silently ignore the error and return 0. - On integer overflow, silently ignore the overflow and truncated the clock to - _PyTime_MIN or _PyTime_MAX. + On integer overflow, silently ignore the overflow and clamp the clock to + [_PyTime_MIN; _PyTime_MAX]. Use _PyTime_GetPerfCounterWithInfo() to check for failure. */ PyAPI_FUNC(_PyTime_t) _PyTime_GetPerfCounter(void); @@ -239,6 +306,15 @@ PyAPI_FUNC(int) _PyTime_GetPerfCounterWithInfo( _PyTime_t *t, _Py_clock_info_t *info); + +// Create a deadline. +// Pseudo code: _PyTime_GetMonotonicClock() + timeout. +PyAPI_FUNC(_PyTime_t) _PyDeadline_Init(_PyTime_t timeout); + +// Get remaining time from a deadline. +// Pseudo code: deadline - _PyTime_GetMonotonicClock(). +PyAPI_FUNC(_PyTime_t) _PyDeadline_Get(_PyTime_t deadline); + #ifdef __cplusplus } #endif diff --git a/include/cpython/setobject.h b/include/cpython/setobject.h new file mode 100644 index 00000000..b4443a67 --- /dev/null +++ b/include/cpython/setobject.h @@ -0,0 +1,67 @@ +#ifndef Py_CPYTHON_SETOBJECT_H +# error "this header file must not be included directly" +#endif + +/* There are three kinds of entries in the table: + +1. Unused: key == NULL and hash == 0 +2. Dummy: key == dummy and hash == -1 +3. Active: key != NULL and key != dummy and hash != -1 + +The hash field of Unused slots is always zero. + +The hash field of Dummy slots are set to -1 +meaning that dummy entries can be detected by +either entry->key==dummy or by entry->hash==-1. +*/ + +#define PySet_MINSIZE 8 + +typedef struct { + PyObject *key; + Py_hash_t hash; /* Cached hash code of the key */ +} setentry; + +/* The SetObject data structure is shared by set and frozenset objects. + +Invariant for sets: + - hash is -1 + +Invariants for frozensets: + - data is immutable. + - hash is the hash of the frozenset or -1 if not computed yet. + +*/ + +typedef struct { + PyObject_HEAD + + Py_ssize_t fill; /* Number active and dummy entries*/ + Py_ssize_t used; /* Number active entries */ + + /* The table contains mask + 1 slots, and that's a power of 2. + * We store the mask instead of the size because the mask is more + * frequently needed. + */ + Py_ssize_t mask; + + /* The table points to a fixed-size smalltable for small tables + * or to additional malloc'ed memory for bigger tables. + * The table pointer is never NULL which saves us from repeated + * runtime null-tests. + */ + setentry *table; + Py_hash_t hash; /* Only used by frozenset objects */ + Py_ssize_t finger; /* Search finger for pop() */ + + setentry smalltable[PySet_MINSIZE]; + PyObject *weakreflist; /* List of weak references */ +} PySetObject; + +#define PySet_GET_SIZE(so) \ + (assert(PyAnySet_Check(so)), (((PySetObject *)(so))->used)) + +PyAPI_DATA(PyObject *) _PySet_Dummy; + +PyAPI_FUNC(int) _PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash); +PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable); diff --git a/include/cpython/sysmodule.h b/include/cpython/sysmodule.h index fc4c899b..19d9dddc 100644 --- a/include/cpython/sysmodule.h +++ b/include/cpython/sysmodule.h @@ -2,8 +2,8 @@ # error "this header file must not be included directly" #endif -PyAPI_FUNC(PyObject *) _PySys_GetObjectId(_Py_Identifier *key); -PyAPI_FUNC(int) _PySys_SetObjectId(_Py_Identifier *key, PyObject *); +PyAPI_FUNC(PyObject *) _PySys_GetAttr(PyThreadState *tstate, + PyObject *name); PyAPI_FUNC(size_t) _PySys_GetSizeOf(PyObject *); diff --git a/include/cpython/traceback.h b/include/cpython/traceback.h index aac5b42c..a4e087b2 100644 --- a/include/cpython/traceback.h +++ b/include/cpython/traceback.h @@ -2,13 +2,15 @@ # error "this header file must not be included directly" #endif -typedef struct _traceback { +typedef struct _traceback PyTracebackObject; + +struct _traceback { PyObject_HEAD - struct _traceback *tb_next; + PyTracebackObject *tb_next; PyFrameObject *tb_frame; int tb_lasti; int tb_lineno; -} PyTracebackObject; +}; -PyAPI_FUNC(int) _Py_DisplaySourceLine(PyObject *, PyObject *, int, int); +PyAPI_FUNC(int) _Py_DisplaySourceLine(PyObject *, PyObject *, int, int, int *, PyObject **); PyAPI_FUNC(void) _PyTraceback_Add(const char *, const char *, int); diff --git a/include/cpython/tupleobject.h b/include/cpython/tupleobject.h index 7cada884..3d9c1aff 100644 --- a/include/cpython/tupleobject.h +++ b/include/cpython/tupleobject.h @@ -13,16 +13,31 @@ typedef struct { PyAPI_FUNC(int) _PyTuple_Resize(PyObject **, Py_ssize_t); PyAPI_FUNC(void) _PyTuple_MaybeUntrack(PyObject *); -/* Macros trading safety for speed */ - /* Cast argument to PyTupleObject* type. */ -#define _PyTuple_CAST(op) (assert(PyTuple_Check(op)), (PyTupleObject *)(op)) +#define _PyTuple_CAST(op) \ + (assert(PyTuple_Check(op)), _Py_CAST(PyTupleObject*, (op))) -#define PyTuple_GET_SIZE(op) Py_SIZE(_PyTuple_CAST(op)) +// Macros and static inline functions, trading safety for speed -#define PyTuple_GET_ITEM(op, i) (_PyTuple_CAST(op)->ob_item[i]) +static inline Py_ssize_t PyTuple_GET_SIZE(PyObject *op) { + PyTupleObject *tuple = _PyTuple_CAST(op); + return Py_SIZE(tuple); +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyTuple_GET_SIZE(op) PyTuple_GET_SIZE(_PyObject_CAST(op)) +#endif -/* Macro, *only* to be used to fill in brand new tuples */ -#define PyTuple_SET_ITEM(op, i, v) ((void)(_PyTuple_CAST(op)->ob_item[i] = v)) +#define PyTuple_GET_ITEM(op, index) (_PyTuple_CAST(op)->ob_item[index]) + +/* Function *only* to be used to fill in brand new tuples */ +static inline void +PyTuple_SET_ITEM(PyObject *op, Py_ssize_t index, PyObject *value) { + PyTupleObject *tuple = _PyTuple_CAST(op); + tuple->ob_item[index] = value; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +#define PyTuple_SET_ITEM(op, index, value) \ + PyTuple_SET_ITEM(_PyObject_CAST(op), index, _PyObject_CAST(value)) +#endif PyAPI_FUNC(void) _PyTuple_DebugMallocStats(FILE *out); diff --git a/include/cpython/unicodeobject.h b/include/cpython/unicodeobject.h index 0761f01e..84307d18 100644 --- a/include/cpython/unicodeobject.h +++ b/include/cpython/unicodeobject.h @@ -45,24 +45,11 @@ #define Py_UNICODE_ISALPHA(ch) _PyUnicode_IsAlpha(ch) #define Py_UNICODE_ISALNUM(ch) \ - (Py_UNICODE_ISALPHA(ch) || \ + (Py_UNICODE_ISALPHA(ch) || \ Py_UNICODE_ISDECIMAL(ch) || \ Py_UNICODE_ISDIGIT(ch) || \ Py_UNICODE_ISNUMERIC(ch)) -Py_DEPRECATED(3.3) static inline void -Py_UNICODE_COPY(Py_UNICODE *target, const Py_UNICODE *source, Py_ssize_t length) { - memcpy(target, source, (size_t)(length) * sizeof(Py_UNICODE)); -} - -Py_DEPRECATED(3.3) static inline void -Py_UNICODE_FILL(Py_UNICODE *target, Py_UNICODE value, Py_ssize_t length) { - Py_ssize_t i; - for (i = 0; i < length; i++) { - target[i] = value; - } -} - /* macros to work with surrogates */ #define Py_UNICODE_IS_SURROGATE(ch) (0xD800 <= (ch) && (ch) <= 0xDFFF) #define Py_UNICODE_IS_HIGH_SURROGATE(ch) (0xD800 <= (ch) && (ch) <= 0xDBFF) @@ -247,40 +234,16 @@ PyAPI_FUNC(int) _PyUnicode_CheckConsistency( PyObject *op, int check_content); -/* Fast access macros */ - -/* Returns the deprecated Py_UNICODE representation's size in code units - (this includes surrogate pairs as 2 units). - If the Py_UNICODE representation is not available, it will be computed - on request. Use PyUnicode_GET_LENGTH() for the length in code points. */ - -/* Py_DEPRECATED(3.3) */ -#define PyUnicode_GET_SIZE(op) \ - (assert(PyUnicode_Check(op)), \ - (((PyASCIIObject *)(op))->wstr) ? \ - PyUnicode_WSTR_LENGTH(op) : \ - ((void)PyUnicode_AsUnicode(_PyObject_CAST(op)),\ - assert(((PyASCIIObject *)(op))->wstr), \ - PyUnicode_WSTR_LENGTH(op))) - -/* Py_DEPRECATED(3.3) */ -#define PyUnicode_GET_DATA_SIZE(op) \ - (PyUnicode_GET_SIZE(op) * Py_UNICODE_SIZE) - -/* Alias for PyUnicode_AsUnicode(). This will create a wchar_t/Py_UNICODE - representation on demand. Using this macro is very inefficient now, - try to port your code to use the new PyUnicode_*BYTE_DATA() macros or - use PyUnicode_WRITE() and PyUnicode_READ(). */ -/* Py_DEPRECATED(3.3) */ -#define PyUnicode_AS_UNICODE(op) \ +#define _PyASCIIObject_CAST(op) \ (assert(PyUnicode_Check(op)), \ - (((PyASCIIObject *)(op))->wstr) ? (((PyASCIIObject *)(op))->wstr) : \ - PyUnicode_AsUnicode(_PyObject_CAST(op))) - -/* Py_DEPRECATED(3.3) */ -#define PyUnicode_AS_DATA(op) \ - ((const char *)(PyUnicode_AS_UNICODE(op))) + _Py_CAST(PyASCIIObject*, (op))) +#define _PyCompactUnicodeObject_CAST(op) \ + (assert(PyUnicode_Check(op)), \ + _Py_CAST(PyCompactUnicodeObject*, (op))) +#define _PyUnicodeObject_CAST(op) \ + (assert(PyUnicode_Check(op)), \ + _Py_CAST(PyUnicodeObject*, (op))) /* --- Flexible String Representation Helper Macros (PEP 393) -------------- */ @@ -292,163 +255,212 @@ PyAPI_FUNC(int) _PyUnicode_CheckConsistency( #define SSTATE_INTERNED_MORTAL 1 #define SSTATE_INTERNED_IMMORTAL 2 +/* Use only if you know it's a string */ +static inline unsigned int PyUnicode_CHECK_INTERNED(PyObject *op) { + return _PyASCIIObject_CAST(op)->state.interned; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyUnicode_CHECK_INTERNED(op) PyUnicode_CHECK_INTERNED(_PyObject_CAST(op)) +#endif + +/* Fast check to determine whether an object is ready. Equivalent to: + PyUnicode_IS_COMPACT(op) || _PyUnicodeObject_CAST(op)->data.any */ +static inline unsigned int PyUnicode_IS_READY(PyObject *op) { + return _PyASCIIObject_CAST(op)->state.ready; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyUnicode_IS_READY(op) PyUnicode_IS_READY(_PyObject_CAST(op)) +#endif + /* Return true if the string contains only ASCII characters, or 0 if not. The string may be compact (PyUnicode_IS_COMPACT_ASCII) or not, but must be ready. */ -#define PyUnicode_IS_ASCII(op) \ - (assert(PyUnicode_Check(op)), \ - assert(PyUnicode_IS_READY(op)), \ - ((PyASCIIObject*)op)->state.ascii) +static inline unsigned int PyUnicode_IS_ASCII(PyObject *op) { + assert(PyUnicode_IS_READY(op)); + return _PyASCIIObject_CAST(op)->state.ascii; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyUnicode_IS_ASCII(op) PyUnicode_IS_ASCII(_PyObject_CAST(op)) +#endif /* Return true if the string is compact or 0 if not. No type checks or Ready calls are performed. */ -#define PyUnicode_IS_COMPACT(op) \ - (((PyASCIIObject*)(op))->state.compact) +static inline unsigned int PyUnicode_IS_COMPACT(PyObject *op) { + return _PyASCIIObject_CAST(op)->state.compact; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyUnicode_IS_COMPACT(op) PyUnicode_IS_COMPACT(_PyObject_CAST(op)) +#endif /* Return true if the string is a compact ASCII string (use PyASCIIObject structure), or 0 if not. No type checks or Ready calls are performed. */ -#define PyUnicode_IS_COMPACT_ASCII(op) \ - (((PyASCIIObject*)op)->state.ascii && PyUnicode_IS_COMPACT(op)) +static inline int PyUnicode_IS_COMPACT_ASCII(PyObject *op) { + return (_PyASCIIObject_CAST(op)->state.ascii && PyUnicode_IS_COMPACT(op)); +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyUnicode_IS_COMPACT_ASCII(op) PyUnicode_IS_COMPACT_ASCII(_PyObject_CAST(op)) +#endif enum PyUnicode_Kind { /* String contains only wstr byte characters. This is only possible when the string was created with a legacy API and _PyUnicode_Ready() has not been called yet. */ PyUnicode_WCHAR_KIND = 0, -/* Return values of the PyUnicode_KIND() macro: */ +/* Return values of the PyUnicode_KIND() function: */ PyUnicode_1BYTE_KIND = 1, PyUnicode_2BYTE_KIND = 2, PyUnicode_4BYTE_KIND = 4 }; -/* Return pointers to the canonical representation cast to unsigned char, - Py_UCS2, or Py_UCS4 for direct character access. - No checks are performed, use PyUnicode_KIND() before to ensure - these will work correctly. */ - -#define PyUnicode_1BYTE_DATA(op) ((Py_UCS1*)PyUnicode_DATA(op)) -#define PyUnicode_2BYTE_DATA(op) ((Py_UCS2*)PyUnicode_DATA(op)) -#define PyUnicode_4BYTE_DATA(op) ((Py_UCS4*)PyUnicode_DATA(op)) - /* Return one of the PyUnicode_*_KIND values defined above. */ #define PyUnicode_KIND(op) \ - (assert(PyUnicode_Check(op)), \ - assert(PyUnicode_IS_READY(op)), \ - ((PyASCIIObject *)(op))->state.kind) + (assert(PyUnicode_IS_READY(op)), \ + _PyASCIIObject_CAST(op)->state.kind) /* Return a void pointer to the raw unicode buffer. */ -#define _PyUnicode_COMPACT_DATA(op) \ - (PyUnicode_IS_ASCII(op) ? \ - ((void*)((PyASCIIObject*)(op) + 1)) : \ - ((void*)((PyCompactUnicodeObject*)(op) + 1))) +static inline void* _PyUnicode_COMPACT_DATA(PyObject *op) { + if (PyUnicode_IS_ASCII(op)) { + return _Py_STATIC_CAST(void*, (_PyASCIIObject_CAST(op) + 1)); + } + return _Py_STATIC_CAST(void*, (_PyCompactUnicodeObject_CAST(op) + 1)); +} -#define _PyUnicode_NONCOMPACT_DATA(op) \ - (assert(((PyUnicodeObject*)(op))->data.any), \ - ((((PyUnicodeObject *)(op))->data.any))) +static inline void* _PyUnicode_NONCOMPACT_DATA(PyObject *op) { + void *data; + assert(!PyUnicode_IS_COMPACT(op)); + data = _PyUnicodeObject_CAST(op)->data.any; + assert(data != NULL); + return data; +} -#define PyUnicode_DATA(op) \ - (assert(PyUnicode_Check(op)), \ - PyUnicode_IS_COMPACT(op) ? _PyUnicode_COMPACT_DATA(op) : \ - _PyUnicode_NONCOMPACT_DATA(op)) +static inline void* PyUnicode_DATA(PyObject *op) { + if (PyUnicode_IS_COMPACT(op)) { + return _PyUnicode_COMPACT_DATA(op); + } + return _PyUnicode_NONCOMPACT_DATA(op); +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyUnicode_DATA(op) PyUnicode_DATA(_PyObject_CAST(op)) +#endif + +/* Return pointers to the canonical representation cast to unsigned char, + Py_UCS2, or Py_UCS4 for direct character access. + No checks are performed, use PyUnicode_KIND() before to ensure + these will work correctly. */ -/* In the access macros below, "kind" may be evaluated more than once. - All other macro parameters are evaluated exactly once, so it is safe - to put side effects into them (such as increasing the index). */ +#define PyUnicode_1BYTE_DATA(op) _Py_STATIC_CAST(Py_UCS1*, PyUnicode_DATA(op)) +#define PyUnicode_2BYTE_DATA(op) _Py_STATIC_CAST(Py_UCS2*, PyUnicode_DATA(op)) +#define PyUnicode_4BYTE_DATA(op) _Py_STATIC_CAST(Py_UCS4*, PyUnicode_DATA(op)) -/* Write into the canonical representation, this macro does not do any sanity +/* Returns the length of the unicode string. The caller has to make sure that + the string has it's canonical representation set before calling + this function. Call PyUnicode_(FAST_)Ready to ensure that. */ +static inline Py_ssize_t PyUnicode_GET_LENGTH(PyObject *op) { + assert(PyUnicode_IS_READY(op)); + return _PyASCIIObject_CAST(op)->length; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyUnicode_GET_LENGTH(op) PyUnicode_GET_LENGTH(_PyObject_CAST(op)) +#endif + +/* Write into the canonical representation, this function does not do any sanity checks and is intended for usage in loops. The caller should cache the - kind and data pointers obtained from other macro calls. + kind and data pointers obtained from other function calls. index is the index in the string (starts at 0) and value is the new code point value which should be written to that location. */ +static inline void PyUnicode_WRITE(int kind, void *data, + Py_ssize_t index, Py_UCS4 value) +{ + if (kind == PyUnicode_1BYTE_KIND) { + assert(value <= 0xffU); + _Py_STATIC_CAST(Py_UCS1*, data)[index] = _Py_STATIC_CAST(Py_UCS1, value); + } + else if (kind == PyUnicode_2BYTE_KIND) { + assert(value <= 0xffffU); + _Py_STATIC_CAST(Py_UCS2*, data)[index] = _Py_STATIC_CAST(Py_UCS2, value); + } + else { + assert(kind == PyUnicode_4BYTE_KIND); + assert(value <= 0x10ffffU); + _Py_STATIC_CAST(Py_UCS4*, data)[index] = value; + } +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 #define PyUnicode_WRITE(kind, data, index, value) \ - do { \ - switch ((kind)) { \ - case PyUnicode_1BYTE_KIND: { \ - ((Py_UCS1 *)(data))[(index)] = (Py_UCS1)(value); \ - break; \ - } \ - case PyUnicode_2BYTE_KIND: { \ - ((Py_UCS2 *)(data))[(index)] = (Py_UCS2)(value); \ - break; \ - } \ - default: { \ - assert((kind) == PyUnicode_4BYTE_KIND); \ - ((Py_UCS4 *)(data))[(index)] = (Py_UCS4)(value); \ - } \ - } \ - } while (0) + PyUnicode_WRITE(_Py_STATIC_CAST(int, kind), _Py_CAST(void*, data), \ + (index), _Py_STATIC_CAST(Py_UCS4, value)) +#endif /* Read a code point from the string's canonical representation. No checks or ready calls are performed. */ +static inline Py_UCS4 PyUnicode_READ(int kind, + const void *data, Py_ssize_t index) +{ + if (kind == PyUnicode_1BYTE_KIND) { + return _Py_STATIC_CAST(const Py_UCS1*, data)[index]; + } + if (kind == PyUnicode_2BYTE_KIND) { + return _Py_STATIC_CAST(const Py_UCS2*, data)[index]; + } + assert(kind == PyUnicode_4BYTE_KIND); + return _Py_STATIC_CAST(const Py_UCS4*, data)[index]; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 #define PyUnicode_READ(kind, data, index) \ - ((Py_UCS4) \ - ((kind) == PyUnicode_1BYTE_KIND ? \ - ((const Py_UCS1 *)(data))[(index)] : \ - ((kind) == PyUnicode_2BYTE_KIND ? \ - ((const Py_UCS2 *)(data))[(index)] : \ - ((const Py_UCS4 *)(data))[(index)] \ - ) \ - )) + PyUnicode_READ(_Py_STATIC_CAST(int, kind), \ + _Py_STATIC_CAST(const void*, data), \ + (index)) +#endif /* PyUnicode_READ_CHAR() is less efficient than PyUnicode_READ() because it calls PyUnicode_KIND() and might call it twice. For single reads, use PyUnicode_READ_CHAR, for multiple consecutive reads callers should cache kind and use PyUnicode_READ instead. */ -#define PyUnicode_READ_CHAR(unicode, index) \ - (assert(PyUnicode_Check(unicode)), \ - assert(PyUnicode_IS_READY(unicode)), \ - (Py_UCS4) \ - (PyUnicode_KIND((unicode)) == PyUnicode_1BYTE_KIND ? \ - ((const Py_UCS1 *)(PyUnicode_DATA((unicode))))[(index)] : \ - (PyUnicode_KIND((unicode)) == PyUnicode_2BYTE_KIND ? \ - ((const Py_UCS2 *)(PyUnicode_DATA((unicode))))[(index)] : \ - ((const Py_UCS4 *)(PyUnicode_DATA((unicode))))[(index)] \ - ) \ - )) - -/* Returns the length of the unicode string. The caller has to make sure that - the string has it's canonical representation set before calling - this macro. Call PyUnicode_(FAST_)Ready to ensure that. */ -#define PyUnicode_GET_LENGTH(op) \ - (assert(PyUnicode_Check(op)), \ - assert(PyUnicode_IS_READY(op)), \ - ((PyASCIIObject *)(op))->length) - - -/* Fast check to determine whether an object is ready. Equivalent to - PyUnicode_IS_COMPACT(op) || ((PyUnicodeObject*)(op))->data.any */ - -#define PyUnicode_IS_READY(op) (((PyASCIIObject*)op)->state.ready) - -/* PyUnicode_READY() does less work than _PyUnicode_Ready() in the best - case. If the canonical representation is not yet set, it will still call - _PyUnicode_Ready(). - Returns 0 on success and -1 on errors. */ -#define PyUnicode_READY(op) \ - (assert(PyUnicode_Check(op)), \ - (PyUnicode_IS_READY(op) ? \ - 0 : _PyUnicode_Ready(_PyObject_CAST(op)))) +static inline Py_UCS4 PyUnicode_READ_CHAR(PyObject *unicode, Py_ssize_t index) +{ + int kind; + assert(PyUnicode_IS_READY(unicode)); + kind = PyUnicode_KIND(unicode); + if (kind == PyUnicode_1BYTE_KIND) { + return PyUnicode_1BYTE_DATA(unicode)[index]; + } + if (kind == PyUnicode_2BYTE_KIND) { + return PyUnicode_2BYTE_DATA(unicode)[index]; + } + assert(kind == PyUnicode_4BYTE_KIND); + return PyUnicode_4BYTE_DATA(unicode)[index]; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyUnicode_READ_CHAR(unicode, index) \ + PyUnicode_READ_CHAR(_PyObject_CAST(unicode), (index)) +#endif /* Return a maximum character value which is suitable for creating another string based on op. This is always an approximation but more efficient than iterating over the string. */ -#define PyUnicode_MAX_CHAR_VALUE(op) \ - (assert(PyUnicode_IS_READY(op)), \ - (PyUnicode_IS_ASCII(op) ? \ - (0x7f) : \ - (PyUnicode_KIND(op) == PyUnicode_1BYTE_KIND ? \ - (0xffU) : \ - (PyUnicode_KIND(op) == PyUnicode_2BYTE_KIND ? \ - (0xffffU) : \ - (0x10ffffU))))) +static inline Py_UCS4 PyUnicode_MAX_CHAR_VALUE(PyObject *op) +{ + int kind; -Py_DEPRECATED(3.3) -static inline Py_ssize_t _PyUnicode_get_wstr_length(PyObject *op) { - return PyUnicode_IS_COMPACT_ASCII(op) ? - ((PyASCIIObject*)op)->length : - ((PyCompactUnicodeObject*)op)->wstr_length; + assert(PyUnicode_IS_READY(op)); + if (PyUnicode_IS_ASCII(op)) { + return 0x7fU; + } + + kind = PyUnicode_KIND(op); + if (kind == PyUnicode_1BYTE_KIND) { + return 0xffU; + } + if (kind == PyUnicode_2BYTE_KIND) { + return 0xffffU; + } + assert(kind == PyUnicode_4BYTE_KIND); + return 0x10ffffU; } -#define PyUnicode_WSTR_LENGTH(op) _PyUnicode_get_wstr_length((PyObject*)op) +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyUnicode_MAX_CHAR_VALUE(op) \ + PyUnicode_MAX_CHAR_VALUE(_PyObject_CAST(op)) +#endif /* === Public API ========================================================= */ @@ -467,12 +479,27 @@ PyAPI_FUNC(PyObject*) PyUnicode_New( objects which were created using the old API to the new flexible format introduced with PEP 393. - Don't call this function directly, use the public PyUnicode_READY() macro + Don't call this function directly, use the public PyUnicode_READY() function instead. */ PyAPI_FUNC(int) _PyUnicode_Ready( PyObject *unicode /* Unicode object */ ); +/* PyUnicode_READY() does less work than _PyUnicode_Ready() in the best + case. If the canonical representation is not yet set, it will still call + _PyUnicode_Ready(). + Returns 0 on success and -1 on errors. */ +static inline int PyUnicode_READY(PyObject *op) +{ + if (PyUnicode_IS_READY(op)) { + return 0; + } + return _PyUnicode_Ready(op); +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyUnicode_READY(op) PyUnicode_READY(_PyObject_CAST(op)) +#endif + /* Get a copy of a Unicode string. */ PyAPI_FUNC(PyObject*) _PyUnicode_Copy( PyObject *unicode @@ -539,20 +566,6 @@ PyAPI_FUNC(void) _PyUnicode_FastFill( Py_UCS4 fill_char ); -/* Create a Unicode Object from the Py_UNICODE buffer u of the given - size. - - u may be NULL which causes the contents to be undefined. It is the - user's responsibility to fill in the needed data afterwards. Note - that modifying the Unicode object contents after construction is - only allowed if u was set to NULL. - - The buffer is copied into the new object. */ -Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject*) PyUnicode_FromUnicode( - const Py_UNICODE *u, /* Unicode buffer */ - Py_ssize_t size /* size of buffer */ - ); - /* Create a new string from a buffer of Py_UCS1, Py_UCS2 or Py_UCS4 characters. Scan the string to find the maximum character. */ PyAPI_FUNC(PyObject*) PyUnicode_FromKindAndData( @@ -573,6 +586,22 @@ PyAPI_FUNC(Py_UCS4) _PyUnicode_FindMaxChar ( Py_ssize_t start, Py_ssize_t end); +/* --- Legacy deprecated API ---------------------------------------------- */ + +/* Create a Unicode Object from the Py_UNICODE buffer u of the given + size. + + u may be NULL which causes the contents to be undefined. It is the + user's responsibility to fill in the needed data afterwards. Note + that modifying the Unicode object contents after construction is + only allowed if u was set to NULL. + + The buffer is copied into the new object. */ +Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject*) PyUnicode_FromUnicode( + const Py_UNICODE *u, /* Unicode buffer */ + Py_ssize_t size /* size of buffer */ + ); + /* Return a read-only pointer to the Unicode object's internal Py_UNICODE buffer. If the wchar_t/Py_UNICODE representation is not yet available, this @@ -598,6 +627,92 @@ Py_DEPRECATED(3.3) PyAPI_FUNC(Py_UNICODE *) PyUnicode_AsUnicodeAndSize( ); +/* Fast access macros */ + +Py_DEPRECATED(3.3) +static inline Py_ssize_t PyUnicode_WSTR_LENGTH(PyObject *op) +{ + if (PyUnicode_IS_COMPACT_ASCII(op)) { + return _PyASCIIObject_CAST(op)->length; + } + else { + return _PyCompactUnicodeObject_CAST(op)->wstr_length; + } +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyUnicode_WSTR_LENGTH(op) PyUnicode_WSTR_LENGTH(_PyObject_CAST(op)) +#endif + +/* Returns the deprecated Py_UNICODE representation's size in code units + (this includes surrogate pairs as 2 units). + If the Py_UNICODE representation is not available, it will be computed + on request. Use PyUnicode_GET_LENGTH() for the length in code points. */ + +Py_DEPRECATED(3.3) +static inline Py_ssize_t PyUnicode_GET_SIZE(PyObject *op) +{ + _Py_COMP_DIAG_PUSH + _Py_COMP_DIAG_IGNORE_DEPR_DECLS + if (_PyASCIIObject_CAST(op)->wstr == _Py_NULL) { + (void)PyUnicode_AsUnicode(op); + assert(_PyASCIIObject_CAST(op)->wstr != _Py_NULL); + } + return PyUnicode_WSTR_LENGTH(op); + _Py_COMP_DIAG_POP +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyUnicode_GET_SIZE(op) PyUnicode_GET_SIZE(_PyObject_CAST(op)) +#endif + +Py_DEPRECATED(3.3) +static inline Py_ssize_t PyUnicode_GET_DATA_SIZE(PyObject *op) +{ + _Py_COMP_DIAG_PUSH + _Py_COMP_DIAG_IGNORE_DEPR_DECLS + return PyUnicode_GET_SIZE(op) * Py_UNICODE_SIZE; + _Py_COMP_DIAG_POP +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyUnicode_GET_DATA_SIZE(op) PyUnicode_GET_DATA_SIZE(_PyObject_CAST(op)) +#endif + +/* Alias for PyUnicode_AsUnicode(). This will create a wchar_t/Py_UNICODE + representation on demand. Using this macro is very inefficient now, + try to port your code to use the new PyUnicode_*BYTE_DATA() macros or + use PyUnicode_WRITE() and PyUnicode_READ(). */ + +Py_DEPRECATED(3.3) +static inline Py_UNICODE* PyUnicode_AS_UNICODE(PyObject *op) +{ + wchar_t *wstr = _PyASCIIObject_CAST(op)->wstr; + if (wstr != _Py_NULL) { + return wstr; + } + + _Py_COMP_DIAG_PUSH + _Py_COMP_DIAG_IGNORE_DEPR_DECLS + return PyUnicode_AsUnicode(op); + _Py_COMP_DIAG_POP +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyUnicode_AS_UNICODE(op) PyUnicode_AS_UNICODE(_PyObject_CAST(op)) +#endif + +Py_DEPRECATED(3.3) +static inline const char* PyUnicode_AS_DATA(PyObject *op) +{ + _Py_COMP_DIAG_PUSH + _Py_COMP_DIAG_IGNORE_DEPR_DECLS + Py_UNICODE *data = PyUnicode_AS_UNICODE(op); + // In C++, casting directly PyUnicode* to const char* is not valid + return _Py_STATIC_CAST(const char*, _Py_STATIC_CAST(const void*, data)); + _Py_COMP_DIAG_POP +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyUnicode_AS_DATA(op) PyUnicode_AS_DATA(_PyObject_CAST(op)) +#endif + + /* --- _PyUnicodeWriter API ----------------------------------------------- */ typedef struct { @@ -743,27 +858,8 @@ PyAPI_FUNC(const char *) PyUnicode_AsUTF8(PyObject *unicode); #define _PyUnicode_AsString PyUnicode_AsUTF8 -/* --- Generic Codecs ----------------------------------------------------- */ - -/* Encodes a Py_UNICODE buffer of the given size and returns a - Python string object. */ -Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject*) PyUnicode_Encode( - const Py_UNICODE *s, /* Unicode char buffer */ - Py_ssize_t size, /* number of Py_UNICODE chars to encode */ - const char *encoding, /* encoding */ - const char *errors /* error handling */ - ); - /* --- UTF-7 Codecs ------------------------------------------------------- */ -Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject*) PyUnicode_EncodeUTF7( - const Py_UNICODE *data, /* Unicode char buffer */ - Py_ssize_t length, /* number of Py_UNICODE chars to encode */ - int base64SetO, /* Encode RFC2152 Set O characters in base64 */ - int base64WhiteSpace, /* Encode whitespace (sp, ht, nl, cr) in base64 */ - const char *errors /* error handling */ - ); - PyAPI_FUNC(PyObject*) _PyUnicode_EncodeUTF7( PyObject *unicode, /* Unicode object */ int base64SetO, /* Encode RFC2152 Set O characters in base64 */ @@ -777,21 +873,8 @@ PyAPI_FUNC(PyObject*) _PyUnicode_AsUTF8String( PyObject *unicode, const char *errors); -Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject*) PyUnicode_EncodeUTF8( - const Py_UNICODE *data, /* Unicode char buffer */ - Py_ssize_t length, /* number of Py_UNICODE chars to encode */ - const char *errors /* error handling */ - ); - /* --- UTF-32 Codecs ------------------------------------------------------ */ -Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject*) PyUnicode_EncodeUTF32( - const Py_UNICODE *data, /* Unicode char buffer */ - Py_ssize_t length, /* number of Py_UNICODE chars to encode */ - const char *errors, /* error handling */ - int byteorder /* byteorder to use 0=BOM+native;-1=LE,1=BE */ - ); - PyAPI_FUNC(PyObject*) _PyUnicode_EncodeUTF32( PyObject *object, /* Unicode object */ const char *errors, /* error handling */ @@ -813,19 +896,7 @@ PyAPI_FUNC(PyObject*) _PyUnicode_EncodeUTF32( If byteorder is 0, the output string will always start with the Unicode BOM mark (U+FEFF). In the other two modes, no BOM mark is prepended. - - Note that Py_UNICODE data is being interpreted as UTF-16 reduced to - UCS-2. This trick makes it possible to add full UTF-16 capabilities - at a later point without compromising the APIs. - */ -Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject*) PyUnicode_EncodeUTF16( - const Py_UNICODE *data, /* Unicode char buffer */ - Py_ssize_t length, /* number of Py_UNICODE chars to encode */ - const char *errors, /* error handling */ - int byteorder /* byteorder to use 0=BOM+native;-1=LE,1=BE */ - ); - PyAPI_FUNC(PyObject*) _PyUnicode_EncodeUTF16( PyObject* unicode, /* Unicode object */ const char *errors, /* error handling */ @@ -841,7 +912,6 @@ PyAPI_FUNC(PyObject*) _PyUnicode_DecodeUnicodeEscapeStateful( const char *errors, /* error handling */ Py_ssize_t *consumed /* bytes consumed */ ); - /* Helper for PyUnicode_DecodeUnicodeEscape that detects invalid escape chars. */ PyAPI_FUNC(PyObject*) _PyUnicode_DecodeUnicodeEscapeInternal( @@ -854,17 +924,7 @@ PyAPI_FUNC(PyObject*) _PyUnicode_DecodeUnicodeEscapeInternal( string. */ ); -Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject*) PyUnicode_EncodeUnicodeEscape( - const Py_UNICODE *data, /* Unicode char buffer */ - Py_ssize_t length /* Number of Py_UNICODE chars to encode */ - ); - -/* --- Raw-Unicode-Escape Codecs ------------------------------------------ */ - -Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject*) PyUnicode_EncodeRawUnicodeEscape( - const Py_UNICODE *data, /* Unicode char buffer */ - Py_ssize_t length /* Number of Py_UNICODE chars to encode */ - ); +/* --- Raw-Unicode-Escape Codecs ---------------------------------------------- */ /* Variant of PyUnicode_DecodeRawUnicodeEscape that supports partial decoding. */ PyAPI_FUNC(PyObject*) _PyUnicode_DecodeRawUnicodeEscapeStateful( @@ -880,42 +940,16 @@ PyAPI_FUNC(PyObject*) _PyUnicode_AsLatin1String( PyObject* unicode, const char* errors); -Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject*) PyUnicode_EncodeLatin1( - const Py_UNICODE *data, /* Unicode char buffer */ - Py_ssize_t length, /* Number of Py_UNICODE chars to encode */ - const char *errors /* error handling */ - ); - /* --- ASCII Codecs ------------------------------------------------------- */ PyAPI_FUNC(PyObject*) _PyUnicode_AsASCIIString( PyObject* unicode, const char* errors); -Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject*) PyUnicode_EncodeASCII( - const Py_UNICODE *data, /* Unicode char buffer */ - Py_ssize_t length, /* Number of Py_UNICODE chars to encode */ - const char *errors /* error handling */ - ); - /* --- Character Map Codecs ----------------------------------------------- */ -Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject*) PyUnicode_EncodeCharmap( - const Py_UNICODE *data, /* Unicode char buffer */ - Py_ssize_t length, /* Number of Py_UNICODE chars to encode */ - PyObject *mapping, /* encoding mapping */ - const char *errors /* error handling */ - ); - -PyAPI_FUNC(PyObject*) _PyUnicode_EncodeCharmap( - PyObject *unicode, /* Unicode object */ - PyObject *mapping, /* encoding mapping */ - const char *errors /* error handling */ - ); - -/* Translate a Py_UNICODE buffer of the given length by applying a - character mapping table to it and return the resulting Unicode - object. +/* Translate an Unicode object by applying a character mapping table to + it and return the resulting Unicode object. The mapping table must map Unicode ordinal integers to Unicode strings, Unicode ordinal integers or None (causing deletion of the character). @@ -923,68 +957,15 @@ PyAPI_FUNC(PyObject*) _PyUnicode_EncodeCharmap( Mapping tables may be dictionaries or sequences. Unmapped character ordinals (ones which cause a LookupError) are left untouched and are copied as-is. - */ -Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject *) PyUnicode_TranslateCharmap( - const Py_UNICODE *data, /* Unicode char buffer */ - Py_ssize_t length, /* Number of Py_UNICODE chars to encode */ - PyObject *table, /* Translate table */ - const char *errors /* error handling */ - ); - -/* --- MBCS codecs for Windows -------------------------------------------- */ - -#ifdef MS_WINDOWS -Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject*) PyUnicode_EncodeMBCS( - const Py_UNICODE *data, /* Unicode char buffer */ - Py_ssize_t length, /* number of Py_UNICODE chars to encode */ +PyAPI_FUNC(PyObject*) _PyUnicode_EncodeCharmap( + PyObject *unicode, /* Unicode object */ + PyObject *mapping, /* encoding mapping */ const char *errors /* error handling */ ); -#endif /* --- Decimal Encoder ---------------------------------------------------- */ -/* Takes a Unicode string holding a decimal value and writes it into - an output buffer using standard ASCII digit codes. - - The output buffer has to provide at least length+1 bytes of storage - area. The output string is 0-terminated. - - The encoder converts whitespace to ' ', decimal characters to their - corresponding ASCII digit and all other Latin-1 characters except - \0 as-is. Characters outside this range (Unicode ordinals 1-256) - are treated as errors. This includes embedded NULL bytes. - - Error handling is defined by the errors argument: - - NULL or "strict": raise a ValueError - "ignore": ignore the wrong characters (these are not copied to the - output buffer) - "replace": replaces illegal characters with '?' - - Returns 0 on success, -1 on failure. - -*/ - -Py_DEPRECATED(3.3) PyAPI_FUNC(int) PyUnicode_EncodeDecimal( - Py_UNICODE *s, /* Unicode buffer */ - Py_ssize_t length, /* Number of Py_UNICODE chars to encode */ - char *output, /* Output buffer; must have size >= length */ - const char *errors /* error handling */ - ); - -/* Transforms code points that have decimal digit property to the - corresponding ASCII digit code points. - - Returns a new Unicode string on success, NULL on failure. -*/ - -Py_DEPRECATED(3.3) -PyAPI_FUNC(PyObject*) PyUnicode_TransformDecimalToASCII( - Py_UNICODE *s, /* Unicode buffer */ - Py_ssize_t length /* Number of Py_UNICODE chars to transform */ - ); - /* Coverts a Unicode object holding a decimal value to an ASCII string for using in int, float and complex parsers. Transforms code points that have decimal digit property to the @@ -1163,6 +1144,9 @@ PyAPI_FUNC(PyObject*) _PyUnicode_FromId(_Py_Identifier*); and where the hash values are equal (i.e. a very probable match) */ PyAPI_FUNC(int) _PyUnicode_EQ(PyObject *, PyObject *); +/* Equality check. Returns -1 on failure. */ +PyAPI_FUNC(int) _PyUnicode_Equal(PyObject *, PyObject *); + PyAPI_FUNC(int) _PyUnicode_WideCharString_Converter(PyObject *, void *); PyAPI_FUNC(int) _PyUnicode_WideCharString_Opt_Converter(PyObject *, void *); diff --git a/include/cpython/warnings.h b/include/cpython/warnings.h new file mode 100644 index 00000000..2ef8e3ce --- /dev/null +++ b/include/cpython/warnings.h @@ -0,0 +1,20 @@ +#ifndef Py_CPYTHON_WARNINGS_H +# error "this header file must not be included directly" +#endif + +PyAPI_FUNC(int) PyErr_WarnExplicitObject( + PyObject *category, + PyObject *message, + PyObject *filename, + int lineno, + PyObject *module, + PyObject *registry); + +PyAPI_FUNC(int) PyErr_WarnExplicitFormat( + PyObject *category, + const char *filename, int lineno, + const char *module, PyObject *registry, + const char *format, ...); + +// DEPRECATED: Use PyErr_WarnEx() instead. +#define PyErr_Warn(category, msg) PyErr_WarnEx(category, msg, 1) diff --git a/include/cpython/weakrefobject.h b/include/cpython/weakrefobject.h new file mode 100644 index 00000000..26b364f4 --- /dev/null +++ b/include/cpython/weakrefobject.h @@ -0,0 +1,58 @@ +#ifndef Py_CPYTHON_WEAKREFOBJECT_H +# error "this header file must not be included directly" +#endif + +/* PyWeakReference is the base struct for the Python ReferenceType, ProxyType, + * and CallableProxyType. + */ +struct _PyWeakReference { + PyObject_HEAD + + /* The object to which this is a weak reference, or Py_None if none. + * Note that this is a stealth reference: wr_object's refcount is + * not incremented to reflect this pointer. + */ + PyObject *wr_object; + + /* A callable to invoke when wr_object dies, or NULL if none. */ + PyObject *wr_callback; + + /* A cache for wr_object's hash code. As usual for hashes, this is -1 + * if the hash code isn't known yet. + */ + Py_hash_t hash; + + /* If wr_object is weakly referenced, wr_object has a doubly-linked NULL- + * terminated list of weak references to it. These are the list pointers. + * If wr_object goes away, wr_object is set to Py_None, and these pointers + * have no meaning then. + */ + PyWeakReference *wr_prev; + PyWeakReference *wr_next; + vectorcallfunc vectorcall; +}; + +PyAPI_FUNC(Py_ssize_t) _PyWeakref_GetWeakrefCount(PyWeakReference *head); + +PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference *self); + +static inline PyObject* PyWeakref_GET_OBJECT(PyObject *ref_obj) { + PyWeakReference *ref; + PyObject *obj; + assert(PyWeakref_Check(ref_obj)); + ref = _Py_CAST(PyWeakReference*, ref_obj); + obj = ref->wr_object; + // Explanation for the Py_REFCNT() check: when a weakref's target is part + // of a long chain of deallocations which triggers the trashcan mechanism, + // clearing the weakrefs can be delayed long after the target's refcount + // has dropped to zero. In the meantime, code accessing the weakref will + // be able to "see" the target object even though it is supposed to be + // unreachable. See issue gh-60806. + if (Py_REFCNT(obj) > 0) { + return obj; + } + return Py_None; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyWeakref_GET_OBJECT(ref) PyWeakref_GET_OBJECT(_PyObject_CAST(ref)) +#endif diff --git a/include/descrobject.h b/include/descrobject.h index 703bc8fd..77f221df 100644 --- a/include/descrobject.h +++ b/include/descrobject.h @@ -8,101 +8,37 @@ extern "C" { typedef PyObject *(*getter)(PyObject *, void *); typedef int (*setter)(PyObject *, PyObject *, void *); -typedef struct PyGetSetDef { +struct PyGetSetDef { const char *name; getter get; setter set; const char *doc; void *closure; -} PyGetSetDef; - -#ifndef Py_LIMITED_API -typedef PyObject *(*wrapperfunc)(PyObject *self, PyObject *args, - void *wrapped); - -typedef PyObject *(*wrapperfunc_kwds)(PyObject *self, PyObject *args, - void *wrapped, PyObject *kwds); - -struct wrapperbase { - const char *name; - int offset; - void *function; - wrapperfunc wrapper; - const char *doc; - int flags; - PyObject *name_strobj; }; -/* Flags for above struct */ -#define PyWrapperFlag_KEYWORDS 1 /* wrapper function takes keyword args */ - -/* Various kinds of descriptor objects */ - -typedef struct { - PyObject_HEAD - PyTypeObject *d_type; - PyObject *d_name; - PyObject *d_qualname; -} PyDescrObject; - -#define PyDescr_COMMON PyDescrObject d_common - -#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type) -#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name) - -typedef struct { - PyDescr_COMMON; - PyMethodDef *d_method; - vectorcallfunc vectorcall; -} PyMethodDescrObject; - -typedef struct { - PyDescr_COMMON; - struct PyMemberDef *d_member; -} PyMemberDescrObject; - -typedef struct { - PyDescr_COMMON; - PyGetSetDef *d_getset; -} PyGetSetDescrObject; - -typedef struct { - PyDescr_COMMON; - struct wrapperbase *d_base; - void *d_wrapped; /* This can be any function pointer */ -} PyWrapperDescrObject; -#endif /* Py_LIMITED_API */ - PyAPI_DATA(PyTypeObject) PyClassMethodDescr_Type; PyAPI_DATA(PyTypeObject) PyGetSetDescr_Type; PyAPI_DATA(PyTypeObject) PyMemberDescr_Type; PyAPI_DATA(PyTypeObject) PyMethodDescr_Type; PyAPI_DATA(PyTypeObject) PyWrapperDescr_Type; PyAPI_DATA(PyTypeObject) PyDictProxy_Type; -#ifndef Py_LIMITED_API -PyAPI_DATA(PyTypeObject) _PyMethodWrapper_Type; -#endif /* Py_LIMITED_API */ +PyAPI_DATA(PyTypeObject) PyProperty_Type; PyAPI_FUNC(PyObject *) PyDescr_NewMethod(PyTypeObject *, PyMethodDef *); PyAPI_FUNC(PyObject *) PyDescr_NewClassMethod(PyTypeObject *, PyMethodDef *); -struct PyMemberDef; /* forward declaration for following prototype */ -PyAPI_FUNC(PyObject *) PyDescr_NewMember(PyTypeObject *, - struct PyMemberDef *); -PyAPI_FUNC(PyObject *) PyDescr_NewGetSet(PyTypeObject *, - struct PyGetSetDef *); -#ifndef Py_LIMITED_API -PyAPI_FUNC(PyObject *) PyDescr_NewWrapper(PyTypeObject *, - struct wrapperbase *, void *); -PyAPI_FUNC(int) PyDescr_IsData(PyObject *); -#endif +PyAPI_FUNC(PyObject *) PyDescr_NewMember(PyTypeObject *, PyMemberDef *); +PyAPI_FUNC(PyObject *) PyDescr_NewGetSet(PyTypeObject *, PyGetSetDef *); PyAPI_FUNC(PyObject *) PyDictProxy_New(PyObject *); PyAPI_FUNC(PyObject *) PyWrapper_New(PyObject *, PyObject *); +#ifndef Py_LIMITED_API +# define Py_CPYTHON_DESCROBJECT_H +# include "cpython/descrobject.h" +# undef Py_CPYTHON_DESCROBJECT_H +#endif -PyAPI_DATA(PyTypeObject) PyProperty_Type; #ifdef __cplusplus } #endif #endif /* !Py_DESCROBJECT_H */ - diff --git a/include/dictobject.h b/include/dictobject.h index da5a36ba..a6233d8a 100644 --- a/include/dictobject.h +++ b/include/dictobject.h @@ -87,7 +87,7 @@ PyAPI_DATA(PyTypeObject) PyDictRevIterValue_Type; #ifndef Py_LIMITED_API # define Py_CPYTHON_DICTOBJECT_H -# include "cpython/dictobject.h" +# include "cpython/dictobject.h" # undef Py_CPYTHON_DICTOBJECT_H #endif diff --git a/include/eval.h b/include/eval.h deleted file mode 100644 index eda28df8..00000000 --- a/include/eval.h +++ /dev/null @@ -1,27 +0,0 @@ - -/* Interface to execute compiled code */ - -#ifndef Py_EVAL_H -#define Py_EVAL_H -#ifdef __cplusplus -extern "C" { -#endif - -PyAPI_FUNC(PyObject *) PyEval_EvalCode(PyObject *, PyObject *, PyObject *); - -PyAPI_FUNC(PyObject *) PyEval_EvalCodeEx(PyObject *co, - PyObject *globals, - PyObject *locals, - PyObject *const *args, int argc, - PyObject *const *kwds, int kwdc, - PyObject *const *defs, int defc, - PyObject *kwdefs, PyObject *closure); - -#ifndef Py_LIMITED_API -PyAPI_FUNC(PyObject *) _PyEval_CallTracing(PyObject *func, PyObject *args); -#endif - -#ifdef __cplusplus -} -#endif -#endif /* !Py_EVAL_H */ diff --git a/include/fileobject.h b/include/fileobject.h index 6ec2994a..4c983e7b 100644 --- a/include/fileobject.h +++ b/include/fileobject.h @@ -39,7 +39,7 @@ PyAPI_DATA(int) Py_UTF8Mode; #ifndef Py_LIMITED_API # define Py_CPYTHON_FILEOBJECT_H -# include "cpython/fileobject.h" +# include "cpython/fileobject.h" # undef Py_CPYTHON_FILEOBJECT_H #endif diff --git a/include/fileutils.h b/include/fileutils.h index 16f3b635..ba5acc84 100644 --- a/include/fileutils.h +++ b/include/fileutils.h @@ -16,7 +16,7 @@ PyAPI_FUNC(char*) Py_EncodeLocale( #ifndef Py_LIMITED_API # define Py_CPYTHON_FILEUTILS_H -# include "cpython/fileutils.h" +# include "cpython/fileutils.h" # undef Py_CPYTHON_FILEUTILS_H #endif diff --git a/include/floatobject.h b/include/floatobject.h index e994aa8f..9d2fff30 100644 --- a/include/floatobject.h +++ b/include/floatobject.h @@ -11,106 +11,42 @@ PyFloatObject represents a (double precision) floating point number. extern "C" { #endif -#ifndef Py_LIMITED_API -typedef struct { - PyObject_HEAD - double ob_fval; -} PyFloatObject; -#endif - PyAPI_DATA(PyTypeObject) PyFloat_Type; #define PyFloat_Check(op) PyObject_TypeCheck(op, &PyFloat_Type) #define PyFloat_CheckExact(op) Py_IS_TYPE(op, &PyFloat_Type) -#ifdef Py_NAN #define Py_RETURN_NAN return PyFloat_FromDouble(Py_NAN) -#endif -#define Py_RETURN_INF(sign) do \ - if (copysign(1., sign) == 1.) { \ - return PyFloat_FromDouble(Py_HUGE_VAL); \ - } else { \ - return PyFloat_FromDouble(-Py_HUGE_VAL); \ +#define Py_RETURN_INF(sign) \ + do { \ + if (copysign(1., sign) == 1.) { \ + return PyFloat_FromDouble(Py_HUGE_VAL); \ + } \ + else { \ + return PyFloat_FromDouble(-Py_HUGE_VAL); \ + } \ } while(0) PyAPI_FUNC(double) PyFloat_GetMax(void); PyAPI_FUNC(double) PyFloat_GetMin(void); -PyAPI_FUNC(PyObject *) PyFloat_GetInfo(void); +PyAPI_FUNC(PyObject*) PyFloat_GetInfo(void); /* Return Python float from string PyObject. */ -PyAPI_FUNC(PyObject *) PyFloat_FromString(PyObject*); +PyAPI_FUNC(PyObject*) PyFloat_FromString(PyObject*); /* Return Python float from C double. */ -PyAPI_FUNC(PyObject *) PyFloat_FromDouble(double); +PyAPI_FUNC(PyObject*) PyFloat_FromDouble(double); /* Extract C double from Python float. The macro version trades safety for speed. */ -PyAPI_FUNC(double) PyFloat_AsDouble(PyObject *); -#ifndef Py_LIMITED_API -#define PyFloat_AS_DOUBLE(op) (((PyFloatObject *)(op))->ob_fval) -#endif +PyAPI_FUNC(double) PyFloat_AsDouble(PyObject*); #ifndef Py_LIMITED_API -/* _PyFloat_{Pack,Unpack}{4,8} - * - * The struct and pickle (at least) modules need an efficient platform- - * independent way to store floating-point values as byte strings. - * The Pack routines produce a string from a C double, and the Unpack - * routines produce a C double from such a string. The suffix (4 or 8) - * specifies the number of bytes in the string. - * - * On platforms that appear to use (see _PyFloat_Init()) IEEE-754 formats - * these functions work by copying bits. On other platforms, the formats the - * 4- byte format is identical to the IEEE-754 single precision format, and - * the 8-byte format to the IEEE-754 double precision format, although the - * packing of INFs and NaNs (if such things exist on the platform) isn't - * handled correctly, and attempting to unpack a string containing an IEEE - * INF or NaN will raise an exception. - * - * On non-IEEE platforms with more precision, or larger dynamic range, than - * 754 supports, not all values can be packed; on non-IEEE platforms with less - * precision, or smaller dynamic range, not all values can be unpacked. What - * happens in such cases is partly accidental (alas). - */ - -/* The pack routines write 2, 4 or 8 bytes, starting at p. le is a bool - * argument, true if you want the string in little-endian format (exponent - * last, at p+1, p+3 or p+7), false if you want big-endian format (exponent - * first, at p). - * Return value: 0 if all is OK, -1 if error (and an exception is - * set, most likely OverflowError). - * There are two problems on non-IEEE platforms: - * 1): What this does is undefined if x is a NaN or infinity. - * 2): -0.0 and +0.0 produce the same string. - */ -PyAPI_FUNC(int) _PyFloat_Pack2(double x, unsigned char *p, int le); -PyAPI_FUNC(int) _PyFloat_Pack4(double x, unsigned char *p, int le); -PyAPI_FUNC(int) _PyFloat_Pack8(double x, unsigned char *p, int le); - -/* The unpack routines read 2, 4 or 8 bytes, starting at p. le is a bool - * argument, true if the string is in little-endian format (exponent - * last, at p+1, p+3 or p+7), false if big-endian (exponent first, at p). - * Return value: The unpacked double. On error, this is -1.0 and - * PyErr_Occurred() is true (and an exception is set, most likely - * OverflowError). Note that on a non-IEEE platform this will refuse - * to unpack a string that represents a NaN or infinity. - */ -PyAPI_FUNC(double) _PyFloat_Unpack2(const unsigned char *p, int le); -PyAPI_FUNC(double) _PyFloat_Unpack4(const unsigned char *p, int le); -PyAPI_FUNC(double) _PyFloat_Unpack8(const unsigned char *p, int le); - -PyAPI_FUNC(void) _PyFloat_DebugMallocStats(FILE* out); - -/* Format the object based on the format_spec, as defined in PEP 3101 - (Advanced String Formatting). */ -PyAPI_FUNC(int) _PyFloat_FormatAdvancedWriter( - _PyUnicodeWriter *writer, - PyObject *obj, - PyObject *format_spec, - Py_ssize_t start, - Py_ssize_t end); -#endif /* Py_LIMITED_API */ +# define Py_CPYTHON_FLOATOBJECT_H +# include "cpython/floatobject.h" +# undef Py_CPYTHON_FLOATOBJECT_H +#endif #ifdef __cplusplus } diff --git a/include/frameobject.h b/include/frameobject.h index c118af12..adb628f6 100644 --- a/include/frameobject.h +++ b/include/frameobject.h @@ -10,7 +10,7 @@ extern "C" { #ifndef Py_LIMITED_API # define Py_CPYTHON_FRAMEOBJECT_H -# include "cpython/frameobject.h" +# include "cpython/frameobject.h" # undef Py_CPYTHON_FRAMEOBJECT_H #endif diff --git a/include/import.h b/include/import.h index aeef3efd..a87677bb 100644 --- a/include/import.h +++ b/include/import.h @@ -88,7 +88,7 @@ PyAPI_FUNC(int) PyImport_AppendInittab( #ifndef Py_LIMITED_API # define Py_CPYTHON_IMPORT_H -# include "cpython/import.h" +# include "cpython/import.h" # undef Py_CPYTHON_IMPORT_H #endif diff --git a/include/internal/pycore_abstract.h b/include/internal/pycore_abstract.h index b791bf24..b1afb2dc 100644 --- a/include/internal/pycore_abstract.h +++ b/include/internal/pycore_abstract.h @@ -16,6 +16,9 @@ _PyIndex_Check(PyObject *obj) return (tp_as_number != NULL && tp_as_number->nb_index != NULL); } +PyObject *_PyNumber_PowerNoMod(PyObject *lhs, PyObject *rhs); +PyObject *_PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs); + #ifdef __cplusplus } #endif diff --git a/include/internal/pycore_asdl.h b/include/internal/pycore_asdl.h index c0b07c31..5b01c7a6 100644 --- a/include/internal/pycore_asdl.h +++ b/include/internal/pycore_asdl.h @@ -78,9 +78,9 @@ asdl_ ## NAME ## _seq *_Py_asdl_ ## NAME ## _seq_new(Py_ssize_t size, PyArena *a return seq; \ } -#define asdl_seq_GET_UNTYPED(S, I) (S)->elements[(I)] -#define asdl_seq_GET(S, I) (S)->typed_elements[(I)] -#define asdl_seq_LEN(S) ((S) == NULL ? 0 : (S)->size) +#define asdl_seq_GET_UNTYPED(S, I) _Py_RVALUE((S)->elements[(I)]) +#define asdl_seq_GET(S, I) _Py_RVALUE((S)->typed_elements[(I)]) +#define asdl_seq_LEN(S) _Py_RVALUE(((S) == NULL ? 0 : (S)->size)) #ifdef Py_DEBUG # define asdl_seq_SET(S, I, V) \ @@ -91,7 +91,7 @@ asdl_ ## NAME ## _seq *_Py_asdl_ ## NAME ## _seq_new(Py_ssize_t size, PyArena *a (S)->typed_elements[_asdl_i] = (V); \ } while (0) #else -# define asdl_seq_SET(S, I, V) (S)->typed_elements[I] = (V) +# define asdl_seq_SET(S, I, V) _Py_RVALUE((S)->typed_elements[I] = (V)) #endif #ifdef Py_DEBUG @@ -103,7 +103,7 @@ asdl_ ## NAME ## _seq *_Py_asdl_ ## NAME ## _seq_new(Py_ssize_t size, PyArena *a (S)->elements[_asdl_i] = (V); \ } while (0) #else -# define asdl_seq_SET_UNTYPED(S, I, V) (S)->elements[I] = (V) +# define asdl_seq_SET_UNTYPED(S, I, V) _Py_RVALUE((S)->elements[I] = (V)) #endif #ifdef __cplusplus diff --git a/include/internal/pycore_ast.h b/include/internal/pycore_ast.h index ebb6a900..36277efe 100644 --- a/include/internal/pycore_ast.h +++ b/include/internal/pycore_ast.h @@ -179,9 +179,9 @@ enum _stmt_kind {FunctionDef_kind=1, AsyncFunctionDef_kind=2, ClassDef_kind=3, AugAssign_kind=7, AnnAssign_kind=8, For_kind=9, AsyncFor_kind=10, While_kind=11, If_kind=12, With_kind=13, AsyncWith_kind=14, Match_kind=15, Raise_kind=16, Try_kind=17, - Assert_kind=18, Import_kind=19, ImportFrom_kind=20, - Global_kind=21, Nonlocal_kind=22, Expr_kind=23, Pass_kind=24, - Break_kind=25, Continue_kind=26}; + TryStar_kind=18, Assert_kind=19, Import_kind=20, + ImportFrom_kind=21, Global_kind=22, Nonlocal_kind=23, + Expr_kind=24, Pass_kind=25, Break_kind=26, Continue_kind=27}; struct _stmt { enum _stmt_kind kind; union { @@ -295,6 +295,13 @@ struct _stmt { asdl_stmt_seq *finalbody; } Try; + struct { + asdl_stmt_seq *body; + asdl_excepthandler_seq *handlers; + asdl_stmt_seq *orelse; + asdl_stmt_seq *finalbody; + } TryStar; + struct { expr_ty test; expr_ty msg; @@ -688,6 +695,10 @@ stmt_ty _PyAST_Try(asdl_stmt_seq * body, asdl_excepthandler_seq * handlers, asdl_stmt_seq * orelse, asdl_stmt_seq * finalbody, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena); +stmt_ty _PyAST_TryStar(asdl_stmt_seq * body, asdl_excepthandler_seq * handlers, + asdl_stmt_seq * orelse, asdl_stmt_seq * finalbody, int + lineno, int col_offset, int end_lineno, int + end_col_offset, PyArena *arena); stmt_ty _PyAST_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena); stmt_ty _PyAST_Import(asdl_alias_seq * names, int lineno, int col_offset, int diff --git a/include/internal/pycore_ast_state.h b/include/internal/pycore_ast_state.h index 882cd09c..f15b4905 100644 --- a/include/internal/pycore_ast_state.h +++ b/include/internal/pycore_ast_state.h @@ -12,6 +12,8 @@ extern "C" { struct ast_state { int initialized; + int recursion_depth; + int recursion_limit; PyObject *AST_type; PyObject *Add_singleton; PyObject *Add_type; @@ -132,6 +134,7 @@ struct ast_state { PyObject *Sub_singleton; PyObject *Sub_type; PyObject *Subscript_type; + PyObject *TryStar_type; PyObject *Try_type; PyObject *Tuple_type; PyObject *TypeIgnore_type; diff --git a/include/internal/pycore_bitutils.h b/include/internal/pycore_bitutils.h index e4aa7a3d..e6bf61ef 100644 --- a/include/internal/pycore_bitutils.h +++ b/include/internal/pycore_bitutils.h @@ -115,8 +115,6 @@ _Py_popcount32(uint32_t x) const uint32_t M2 = 0x33333333; // Binary: 0000 1111 0000 1111 ... const uint32_t M4 = 0x0F0F0F0F; - // 256**4 + 256**3 + 256**2 + 256**1 - const uint32_t SUM = 0x01010101; // Put count of each 2 bits into those 2 bits x = x - ((x >> 1) & M1); @@ -124,8 +122,20 @@ _Py_popcount32(uint32_t x) x = (x & M2) + ((x >> 2) & M2); // Put count of each 8 bits into those 8 bits x = (x + (x >> 4)) & M4; - // Sum of the 4 byte counts - return (uint32_t)((uint64_t)x * (uint64_t)SUM) >> 24; + // Sum of the 4 byte counts. + // Take care when considering changes to the next line. Portability and + // correctness are delicate here, thanks to C's "integer promotions" (C99 + // 搂6.3.1.1p2). On machines where the `int` type has width greater than 32 + // bits, `x` will be promoted to an `int`, and following C's "usual + // arithmetic conversions" (C99 搂6.3.1.8), the multiplication will be + // performed as a multiplication of two `unsigned int` operands. In this + // case it's critical that we cast back to `uint32_t` in order to keep only + // the least significant 32 bits. On machines where the `int` type has + // width no greater than 32, the multiplication is of two 32-bit unsigned + // integer types, and the (uint32_t) cast is a no-op. In both cases, we + // avoid the risk of undefined behaviour due to overflow of a + // multiplication of signed integer types. + return (uint32_t)(x * 0x01010101U) >> 24; #endif } diff --git a/include/internal/pycore_bytesobject.h b/include/internal/pycore_bytesobject.h new file mode 100644 index 00000000..9173a4f1 --- /dev/null +++ b/include/internal/pycore_bytesobject.h @@ -0,0 +1,52 @@ +#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_InitTypes(PyInterpreterState *); + + +/* Substring Search. + + Returns the index of the first occurrence of + a substring ("needle") in a larger text ("haystack"). + If the needle is not found, return -1. + If the needle is found, add offset to the index. +*/ + +PyAPI_FUNC(Py_ssize_t) +_PyBytes_Find(const char *haystack, Py_ssize_t len_haystack, + const char *needle, Py_ssize_t len_needle, + Py_ssize_t offset); + +/* Same as above, but search right-to-left */ +PyAPI_FUNC(Py_ssize_t) +_PyBytes_ReverseFind(const char *haystack, Py_ssize_t len_haystack, + const char *needle, Py_ssize_t len_needle, + Py_ssize_t offset); + + +/** Helper function to implement the repeat and inplace repeat methods on a buffer + * + * len_dest is assumed to be an integer multiple of len_src. + * If src equals dest, then assume the operation is inplace. + * + * This method repeately doubles the number of bytes copied to reduce + * the number of invocations of memcpy. + */ +PyAPI_FUNC(void) +_PyBytes_Repeat(char* dest, Py_ssize_t len_dest, + const char* src, Py_ssize_t len_src); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_BYTESOBJECT_H */ diff --git a/include/internal/pycore_call.h b/include/internal/pycore_call.h index f7d856a5..3ccacfa0 100644 --- a/include/internal/pycore_call.h +++ b/include/internal/pycore_call.h @@ -8,6 +8,8 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_pystate.h" // _PyThreadState_GET() + PyAPI_FUNC(PyObject *) _PyObject_Call_Prepend( PyThreadState *tstate, PyObject *callable, @@ -28,11 +30,91 @@ PyAPI_FUNC(PyObject *) _PyObject_Call( PyObject *args, PyObject *kwargs); +extern PyObject * _PyObject_CallMethodFormat( + PyThreadState *tstate, PyObject *callable, const char *format, ...); + + +// Static inline variant of public PyVectorcall_Function(). +static inline vectorcallfunc +_PyVectorcall_FunctionInline(PyObject *callable) +{ + assert(callable != NULL); + + PyTypeObject *tp = Py_TYPE(callable); + if (!PyType_HasFeature(tp, Py_TPFLAGS_HAVE_VECTORCALL)) { + return NULL; + } + assert(PyCallable_Check(callable)); + + Py_ssize_t offset = tp->tp_vectorcall_offset; + assert(offset > 0); + + vectorcallfunc ptr; + memcpy(&ptr, (char *) callable + offset, sizeof(ptr)); + return ptr; +} + + +/* Call the callable object 'callable' with the "vectorcall" calling + convention. + + args is a C array for positional arguments. + + nargsf is the number of positional arguments plus optionally the flag + PY_VECTORCALL_ARGUMENTS_OFFSET which means that the caller is allowed to + modify args[-1]. + + kwnames is a tuple of keyword names. The values of the keyword arguments + are stored in "args" after the positional arguments (note that the number + of keyword arguments does not change nargsf). kwnames can also be NULL if + there are no keyword arguments. + + keywords must only contain strings and all keys must be unique. + + Return the result on success. Raise an exception and return NULL on + error. */ +static inline PyObject * +_PyObject_VectorcallTstate(PyThreadState *tstate, PyObject *callable, + PyObject *const *args, size_t nargsf, + PyObject *kwnames) +{ + vectorcallfunc func; + PyObject *res; + + assert(kwnames == NULL || PyTuple_Check(kwnames)); + assert(args != NULL || PyVectorcall_NARGS(nargsf) == 0); + + func = _PyVectorcall_FunctionInline(callable); + if (func == NULL) { + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + return _PyObject_MakeTpCall(tstate, callable, args, nargs, kwnames); + } + res = func(callable, args, nargsf, kwnames); + return _Py_CheckFunctionResult(tstate, callable, res, NULL); +} + + static inline PyObject * -_PyObject_CallNoArgTstate(PyThreadState *tstate, PyObject *func) { +_PyObject_CallNoArgsTstate(PyThreadState *tstate, PyObject *func) { return _PyObject_VectorcallTstate(tstate, func, NULL, 0, NULL); } + +// Private static inline function variant of public PyObject_CallNoArgs() +static inline PyObject * +_PyObject_CallNoArgs(PyObject *func) { + PyThreadState *tstate = _PyThreadState_GET(); + return _PyObject_VectorcallTstate(tstate, func, NULL, 0, NULL); +} + + +static inline PyObject * +_PyObject_FastCallTstate(PyThreadState *tstate, PyObject *func, PyObject *const *args, Py_ssize_t nargs) +{ + return _PyObject_VectorcallTstate(tstate, func, args, (size_t)nargs, NULL); +} + + #ifdef __cplusplus } #endif diff --git a/include/internal/pycore_ceval.h b/include/internal/pycore_ceval.h index f573c3e5..8d18d200 100644 --- a/include/internal/pycore_ceval.h +++ b/include/internal/pycore_ceval.h @@ -12,11 +12,24 @@ extern "C" { struct pyruntimestate; struct _ceval_runtime_state; -#include "pycore_interp.h" /* PyInterpreterState.eval_frame */ +/* WASI has limited call stack. Python's recursion limit depends on code + layout, optimization, and WASI runtime. Wasmtime can handle about 700-750 + recursions, sometimes less. 600 is a more conservative limit. */ +#ifndef Py_DEFAULT_RECURSION_LIMIT +# ifdef __wasi__ +# define Py_DEFAULT_RECURSION_LIMIT 600 +# else +# define Py_DEFAULT_RECURSION_LIMIT 1000 +# endif +#endif + +#include "pycore_interp.h" // PyInterpreterState.eval_frame +#include "pycore_pystate.h" // _PyThreadState_GET() + extern void _Py_FinishPendingCalls(PyThreadState *tstate); extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *); -extern int _PyEval_InitState(struct _ceval_state *ceval); +extern void _PyEval_InitState(struct _ceval_state *, PyThread_type_lock); extern void _PyEval_FiniState(struct _ceval_state *ceval); PyAPI_FUNC(void) _PyEval_SignalReceived(PyInterpreterState *interp); PyAPI_FUNC(int) _PyEval_AddPendingCall( @@ -27,36 +40,48 @@ PyAPI_FUNC(void) _PyEval_SignalAsyncExc(PyInterpreterState *interp); #ifdef HAVE_FORK extern PyStatus _PyEval_ReInitThreads(PyThreadState *tstate); #endif -PyAPI_FUNC(void) _PyEval_SetCoroutineOriginTrackingDepth( - PyThreadState *tstate, - int new_depth); -void _PyEval_Fini(void); +// Used by sys.call_tracing() +extern PyObject* _PyEval_CallTracing(PyObject *func, PyObject *args); + +// Used by sys.get_asyncgen_hooks() +extern PyObject* _PyEval_GetAsyncGenFirstiter(void); +extern PyObject* _PyEval_GetAsyncGenFinalizer(void); + +// Used by sys.set_asyncgen_hooks() +extern int _PyEval_SetAsyncGenFirstiter(PyObject *); +extern int _PyEval_SetAsyncGenFinalizer(PyObject *); + +// Used by sys.get_coroutine_origin_tracking_depth() +// and sys.set_coroutine_origin_tracking_depth() +extern int _PyEval_GetCoroutineOriginTrackingDepth(void); +extern int _PyEval_SetCoroutineOriginTrackingDepth(int depth); + +extern void _PyEval_Fini(void); extern PyObject* _PyEval_GetBuiltins(PyThreadState *tstate); -extern PyObject *_PyEval_BuiltinsFromGlobals( +extern PyObject* _PyEval_BuiltinsFromGlobals( PyThreadState *tstate, PyObject *globals); static inline PyObject* -_PyEval_EvalFrame(PyThreadState *tstate, PyFrameObject *f, int throwflag) +_PyEval_EvalFrame(PyThreadState *tstate, struct _PyInterpreterFrame *frame, int throwflag) { - return tstate->interp->eval_frame(tstate, f, throwflag); + if (tstate->interp->eval_frame == NULL) { + return _PyEval_EvalFrameDefault(tstate, frame, throwflag); + } + return tstate->interp->eval_frame(tstate, frame, throwflag); } -extern PyObject * +extern PyObject* _PyEval_Vector(PyThreadState *tstate, - PyFrameConstructor *desc, PyObject *locals, + PyFunctionObject *func, PyObject *locals, PyObject* const* args, size_t argcount, PyObject *kwnames); -#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS -extern int _PyEval_ThreadsInitialized(PyInterpreterState *interp); -#else extern int _PyEval_ThreadsInitialized(struct pyruntimestate *runtime); -#endif extern PyStatus _PyEval_InitGIL(PyThreadState *tstate); extern void _PyEval_FiniGIL(PyInterpreterState *interp); @@ -69,14 +94,14 @@ extern void _PyEval_DeactivateOpCache(void); #ifdef USE_STACKCHECK /* With USE_STACKCHECK macro defined, trigger stack checks in - _Py_CheckRecursiveCall() on every 64th call to Py_EnterRecursiveCall. */ + _Py_CheckRecursiveCall() on every 64th call to _Py_EnterRecursiveCall. */ static inline int _Py_MakeRecCheck(PyThreadState *tstate) { - return (++tstate->recursion_depth > tstate->interp->ceval.recursion_limit - || ++tstate->stackcheck_counter > 64); + return (tstate->recursion_remaining-- <= 0 + || (tstate->recursion_remaining & 63) == 0); } #else static inline int _Py_MakeRecCheck(PyThreadState *tstate) { - return (++tstate->recursion_depth > tstate->interp->ceval.recursion_limit); + return tstate->recursion_remaining-- <= 0; } #endif @@ -84,29 +109,28 @@ PyAPI_FUNC(int) _Py_CheckRecursiveCall( PyThreadState *tstate, const char *where); -static inline int _Py_EnterRecursiveCall(PyThreadState *tstate, - const char *where) { +static inline int _Py_EnterRecursiveCallTstate(PyThreadState *tstate, + const char *where) { return (_Py_MakeRecCheck(tstate) && _Py_CheckRecursiveCall(tstate, where)); } -static inline int _Py_EnterRecursiveCall_inline(const char *where) { - PyThreadState *tstate = PyThreadState_GET(); - return _Py_EnterRecursiveCall(tstate, where); +static inline int _Py_EnterRecursiveCall(const char *where) { + PyThreadState *tstate = _PyThreadState_GET(); + return _Py_EnterRecursiveCallTstate(tstate, where); } -#define Py_EnterRecursiveCall(where) _Py_EnterRecursiveCall_inline(where) - -static inline void _Py_LeaveRecursiveCall(PyThreadState *tstate) { - tstate->recursion_depth--; +static inline void _Py_LeaveRecursiveCallTstate(PyThreadState *tstate) { + tstate->recursion_remaining++; } -static inline void _Py_LeaveRecursiveCall_inline(void) { - PyThreadState *tstate = PyThreadState_GET(); - _Py_LeaveRecursiveCall(tstate); +static inline void _Py_LeaveRecursiveCall(void) { + PyThreadState *tstate = _PyThreadState_GET(); + _Py_LeaveRecursiveCallTstate(tstate); } -#define Py_LeaveRecursiveCall() _Py_LeaveRecursiveCall_inline() +extern struct _PyInterpreterFrame* _PyEval_GetFrame(void); +extern PyObject* _Py_MakeCoro(PyFunctionObject *func); #ifdef __cplusplus } diff --git a/include/internal/pycore_code.h b/include/internal/pycore_code.h index 8ff1863d..3a24a654 100644 --- a/include/internal/pycore_code.h +++ b/include/internal/pycore_code.h @@ -4,28 +4,558 @@ extern "C" { #endif +/* PEP 659 + * Specialization and quickening structs and helper functions + */ + + +// Inline caches. If you change the number of cache entries for an instruction, +// you must *also* update the number of cache entries in Lib/opcode.py and bump +// the magic number in Lib/importlib/_bootstrap_external.py! + +#define CACHE_ENTRIES(cache) (sizeof(cache)/sizeof(_Py_CODEUNIT)) + +typedef struct { + _Py_CODEUNIT counter; + _Py_CODEUNIT index; + _Py_CODEUNIT module_keys_version[2]; + _Py_CODEUNIT builtin_keys_version; +} _PyLoadGlobalCache; + +#define INLINE_CACHE_ENTRIES_LOAD_GLOBAL CACHE_ENTRIES(_PyLoadGlobalCache) + +typedef struct { + _Py_CODEUNIT counter; +} _PyBinaryOpCache; + +#define INLINE_CACHE_ENTRIES_BINARY_OP CACHE_ENTRIES(_PyBinaryOpCache) + +typedef struct { + _Py_CODEUNIT counter; +} _PyUnpackSequenceCache; + +#define INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE \ + CACHE_ENTRIES(_PyUnpackSequenceCache) + +typedef struct { + _Py_CODEUNIT counter; + _Py_CODEUNIT mask; +} _PyCompareOpCache; + +#define INLINE_CACHE_ENTRIES_COMPARE_OP CACHE_ENTRIES(_PyCompareOpCache) + typedef struct { - PyObject *ptr; /* Cached pointer (borrowed reference) */ - uint64_t globals_ver; /* ma_version of global dict */ - uint64_t builtins_ver; /* ma_version of builtin dict */ -} _PyOpcache_LoadGlobal; + _Py_CODEUNIT counter; + _Py_CODEUNIT type_version[2]; + _Py_CODEUNIT func_version; +} _PyBinarySubscrCache; + +#define INLINE_CACHE_ENTRIES_BINARY_SUBSCR CACHE_ENTRIES(_PyBinarySubscrCache) + +typedef struct { + _Py_CODEUNIT counter; + _Py_CODEUNIT version[2]; + _Py_CODEUNIT index; +} _PyAttrCache; + +#define INLINE_CACHE_ENTRIES_LOAD_ATTR CACHE_ENTRIES(_PyAttrCache) + +#define INLINE_CACHE_ENTRIES_STORE_ATTR CACHE_ENTRIES(_PyAttrCache) + +typedef struct { + _Py_CODEUNIT counter; + _Py_CODEUNIT type_version[2]; + _Py_CODEUNIT dict_offset; + _Py_CODEUNIT keys_version[2]; + _Py_CODEUNIT descr[4]; +} _PyLoadMethodCache; + +#define INLINE_CACHE_ENTRIES_LOAD_METHOD CACHE_ENTRIES(_PyLoadMethodCache) typedef struct { - PyTypeObject *type; - Py_ssize_t hint; - unsigned int tp_version_tag; -} _PyOpCodeOpt_LoadAttr; + _Py_CODEUNIT counter; + _Py_CODEUNIT func_version[2]; + _Py_CODEUNIT min_args; +} _PyCallCache; + +#define INLINE_CACHE_ENTRIES_CALL CACHE_ENTRIES(_PyCallCache) + +typedef struct { + _Py_CODEUNIT counter; +} _PyPrecallCache; + +#define INLINE_CACHE_ENTRIES_PRECALL CACHE_ENTRIES(_PyPrecallCache) + +typedef struct { + _Py_CODEUNIT counter; +} _PyStoreSubscrCache; + +#define INLINE_CACHE_ENTRIES_STORE_SUBSCR CACHE_ENTRIES(_PyStoreSubscrCache) + +#define QUICKENING_WARMUP_DELAY 8 -struct _PyOpcache { - union { - _PyOpcache_LoadGlobal lg; - _PyOpCodeOpt_LoadAttr la; - } u; - char optimized; +/* We want to compare to zero for efficiency, so we offset values accordingly */ +#define QUICKENING_INITIAL_WARMUP_VALUE (-QUICKENING_WARMUP_DELAY) + +void _PyCode_Quicken(PyCodeObject *code); + +static inline void +_PyCode_Warmup(PyCodeObject *code) +{ + if (code->co_warmup != 0) { + code->co_warmup++; + if (code->co_warmup == 0) { + _PyCode_Quicken(code); + } + } +} + +extern uint8_t _PyOpcode_Adaptive[256]; + +extern Py_ssize_t _Py_QuickenedCount; + +// Borrowed references to common callables: +struct callable_cache { + PyObject *isinstance; + PyObject *len; + PyObject *list_append; +}; + +/* "Locals plus" for a code object is the set of locals + cell vars + + * free vars. This relates to variable names as well as offsets into + * the "fast locals" storage array of execution frames. The compiler + * builds the list of names, their offsets, and the corresponding + * kind of local. + * + * Those kinds represent the source of the initial value and the + * variable's scope (as related to closures). A "local" is an + * argument or other variable defined in the current scope. A "free" + * variable is one that is defined in an outer scope and comes from + * the function's closure. A "cell" variable is a local that escapes + * into an inner function as part of a closure, and thus must be + * wrapped in a cell. Any "local" can also be a "cell", but the + * "free" kind is mutually exclusive with both. + */ + +// Note that these all fit within a byte, as do combinations. +// Later, we will use the smaller numbers to differentiate the different +// kinds of locals (e.g. pos-only arg, varkwargs, local-only). +#define CO_FAST_LOCAL 0x20 +#define CO_FAST_CELL 0x40 +#define CO_FAST_FREE 0x80 + +typedef unsigned char _PyLocals_Kind; + +static inline _PyLocals_Kind +_PyLocals_GetKind(PyObject *kinds, int i) +{ + assert(PyBytes_Check(kinds)); + assert(0 <= i && i < PyBytes_GET_SIZE(kinds)); + char *ptr = PyBytes_AS_STRING(kinds); + return (_PyLocals_Kind)(ptr[i]); +} + +static inline void +_PyLocals_SetKind(PyObject *kinds, int i, _PyLocals_Kind kind) +{ + assert(PyBytes_Check(kinds)); + assert(0 <= i && i < PyBytes_GET_SIZE(kinds)); + char *ptr = PyBytes_AS_STRING(kinds); + ptr[i] = (char) kind; +} + + +struct _PyCodeConstructor { + /* metadata */ + PyObject *filename; + PyObject *name; + PyObject *qualname; + int flags; + + /* the code */ + PyObject *code; + int firstlineno; + PyObject *linetable; + + /* used by the code */ + PyObject *consts; + PyObject *names; + + /* mapping frame offsets to information */ + PyObject *localsplusnames; // Tuple of strings + PyObject *localspluskinds; // Bytes object, one byte per variable + + /* args (within varnames) */ + int argcount; + int posonlyargcount; + // XXX Replace argcount with posorkwargcount (argcount - posonlyargcount). + int kwonlyargcount; + + /* needed to create the frame */ + int stacksize; + + /* used by the eval loop */ + PyObject *exceptiontable; }; +// Using an "arguments struct" like this is helpful for maintainability +// in a case such as this with many parameters. It does bear a risk: +// if the struct changes and callers are not updated properly then the +// compiler will not catch problems (like a missing argument). This can +// cause hard-to-debug problems. The risk is mitigated by the use of +// check_code() in codeobject.c. However, we may decide to switch +// back to a regular function signature. Regardless, this approach +// wouldn't be appropriate if this weren't a strictly internal API. +// (See the comments in https://github.com/python/cpython/pull/26258.) +PyAPI_FUNC(int) _PyCode_Validate(struct _PyCodeConstructor *); +PyAPI_FUNC(PyCodeObject *) _PyCode_New(struct _PyCodeConstructor *); + + /* Private API */ -int _PyCode_InitOpcache(PyCodeObject *co); + +/* Getters for internal PyCodeObject data. */ +extern PyObject* _PyCode_GetVarnames(PyCodeObject *); +extern PyObject* _PyCode_GetCellvars(PyCodeObject *); +extern PyObject* _PyCode_GetFreevars(PyCodeObject *); +extern PyObject* _PyCode_GetCode(PyCodeObject *); + +/** API for initializing the line number tables. */ +extern int _PyCode_InitAddressRange(PyCodeObject* co, PyCodeAddressRange *bounds); + +/** Out of process API for initializing the location table. */ +extern void _PyLineTable_InitAddressRange( + const char *linetable, + Py_ssize_t length, + int firstlineno, + PyCodeAddressRange *range); + +/** API for traversing the line number table. */ +extern int _PyLineTable_NextAddressRange(PyCodeAddressRange *range); +extern int _PyLineTable_PreviousAddressRange(PyCodeAddressRange *range); + +/* Specialization functions */ + +extern int _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, + PyObject *name); +extern int _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, + PyObject *name); +extern int _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, _Py_CODEUNIT *instr, PyObject *name); +extern int _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, + PyObject *name); +extern int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr); +extern int _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr); +extern int _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, + int nargs, PyObject *kwnames); +extern int _Py_Specialize_Precall(PyObject *callable, _Py_CODEUNIT *instr, + int nargs, PyObject *kwnames, int oparg); +extern void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, + int oparg, PyObject **locals); +extern void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, + _Py_CODEUNIT *instr, int oparg); +extern void _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, + int oparg); + +/* Deallocator function for static codeobjects used in deepfreeze.py */ +extern void _PyStaticCode_Dealloc(PyCodeObject *co); +/* Function to intern strings of codeobjects */ +extern int _PyStaticCode_InternStrings(PyCodeObject *co); + +#ifdef Py_STATS + +#define SPECIALIZATION_FAILURE_KINDS 30 + +typedef struct _specialization_stats { + uint64_t success; + uint64_t failure; + uint64_t hit; + uint64_t deferred; + uint64_t miss; + uint64_t deopt; + uint64_t failure_kinds[SPECIALIZATION_FAILURE_KINDS]; +} SpecializationStats; + +typedef struct _opcode_stats { + SpecializationStats specialization; + uint64_t execution_count; + uint64_t pair_count[256]; +} OpcodeStats; + +typedef struct _call_stats { + uint64_t inlined_py_calls; + uint64_t pyeval_calls; + uint64_t frames_pushed; + uint64_t frame_objects_created; +} CallStats; + +typedef struct _object_stats { + uint64_t allocations; + uint64_t allocations512; + uint64_t allocations4k; + uint64_t allocations_big; + uint64_t frees; + uint64_t to_freelist; + uint64_t from_freelist; + uint64_t new_values; + uint64_t dict_materialized_on_request; + uint64_t dict_materialized_new_key; + uint64_t dict_materialized_too_big; + uint64_t dict_materialized_str_subclass; +} ObjectStats; + +typedef struct _stats { + OpcodeStats opcode_stats[256]; + CallStats call_stats; + ObjectStats object_stats; +} PyStats; + +extern PyStats _py_stats; + +#define STAT_INC(opname, name) _py_stats.opcode_stats[opname].specialization.name++ +#define STAT_DEC(opname, name) _py_stats.opcode_stats[opname].specialization.name-- +#define OPCODE_EXE_INC(opname) _py_stats.opcode_stats[opname].execution_count++ +#define CALL_STAT_INC(name) _py_stats.call_stats.name++ +#define OBJECT_STAT_INC(name) _py_stats.object_stats.name++ +#define OBJECT_STAT_INC_COND(name, cond) \ + do { if (cond) _py_stats.object_stats.name++; } while (0) + +extern void _Py_PrintSpecializationStats(int to_file); + +// Used by the _opcode extension which is built as a shared library +PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void); + +#else +#define STAT_INC(opname, name) ((void)0) +#define STAT_DEC(opname, name) ((void)0) +#define OPCODE_EXE_INC(opname) ((void)0) +#define CALL_STAT_INC(name) ((void)0) +#define OBJECT_STAT_INC(name) ((void)0) +#define OBJECT_STAT_INC_COND(name, cond) ((void)0) +#endif // !Py_STATS + +// Cache values are only valid in memory, so use native endianness. +#ifdef WORDS_BIGENDIAN + +static inline void +write_u32(uint16_t *p, uint32_t val) +{ + p[0] = (uint16_t)(val >> 16); + p[1] = (uint16_t)(val >> 0); +} + +static inline void +write_u64(uint16_t *p, uint64_t val) +{ + p[0] = (uint16_t)(val >> 48); + p[1] = (uint16_t)(val >> 32); + p[2] = (uint16_t)(val >> 16); + p[3] = (uint16_t)(val >> 0); +} + +static inline uint32_t +read_u32(uint16_t *p) +{ + uint32_t val = 0; + val |= (uint32_t)p[0] << 16; + val |= (uint32_t)p[1] << 0; + return val; +} + +static inline uint64_t +read_u64(uint16_t *p) +{ + uint64_t val = 0; + val |= (uint64_t)p[0] << 48; + val |= (uint64_t)p[1] << 32; + val |= (uint64_t)p[2] << 16; + val |= (uint64_t)p[3] << 0; + return val; +} + +#else + +static inline void +write_u32(uint16_t *p, uint32_t val) +{ + p[0] = (uint16_t)(val >> 0); + p[1] = (uint16_t)(val >> 16); +} + +static inline void +write_u64(uint16_t *p, uint64_t val) +{ + p[0] = (uint16_t)(val >> 0); + p[1] = (uint16_t)(val >> 16); + p[2] = (uint16_t)(val >> 32); + p[3] = (uint16_t)(val >> 48); +} + +static inline uint32_t +read_u32(uint16_t *p) +{ + uint32_t val = 0; + val |= (uint32_t)p[0] << 0; + val |= (uint32_t)p[1] << 16; + return val; +} + +static inline uint64_t +read_u64(uint16_t *p) +{ + uint64_t val = 0; + val |= (uint64_t)p[0] << 0; + val |= (uint64_t)p[1] << 16; + val |= (uint64_t)p[2] << 32; + val |= (uint64_t)p[3] << 48; + return val; +} + +#endif + +static inline void +write_obj(uint16_t *p, PyObject *obj) +{ + uintptr_t val = (uintptr_t)obj; +#if SIZEOF_VOID_P == 8 + write_u64(p, val); +#elif SIZEOF_VOID_P == 4 + write_u32(p, val); +#else + #error "SIZEOF_VOID_P must be 4 or 8" +#endif +} + +static inline PyObject * +read_obj(uint16_t *p) +{ + uintptr_t val; +#if SIZEOF_VOID_P == 8 + val = read_u64(p); +#elif SIZEOF_VOID_P == 4 + val = read_u32(p); +#else + #error "SIZEOF_VOID_P must be 4 or 8" +#endif + return (PyObject *)val; +} + +/* See Objects/exception_handling_notes.txt for details. + */ +static inline unsigned char * +parse_varint(unsigned char *p, int *result) { + int val = p[0] & 63; + while (p[0] & 64) { + p++; + val = (val << 6) | (p[0] & 63); + } + *result = val; + return p+1; +} + +static inline int +write_varint(uint8_t *ptr, unsigned int val) +{ + int written = 1; + while (val >= 64) { + *ptr++ = 64 | (val & 63); + val >>= 6; + written++; + } + *ptr = val; + return written; +} + +static inline int +write_signed_varint(uint8_t *ptr, int val) +{ + if (val < 0) { + val = ((-val)<<1) | 1; + } + else { + val = val << 1; + } + return write_varint(ptr, val); +} + +static inline int +write_location_entry_start(uint8_t *ptr, int code, int length) +{ + assert((code & 15) == code); + *ptr = 128 | (code << 3) | (length - 1); + return 1; +} + + +/** Counters + * The first 16-bit value in each inline cache is a counter. + * When counting misses, the counter is treated as a simple unsigned value. + * + * When counting executions until the next specialization attempt, + * exponential backoff is used to reduce the number of specialization failures. + * The high 12 bits store the counter, the low 4 bits store the backoff exponent. + * On a specialization failure, the backoff exponent is incremented and the + * counter set to (2**backoff - 1). + * Backoff == 6 -> starting counter == 63, backoff == 10 -> starting counter == 1023. + */ + +/* With a 16-bit counter, we have 12 bits for the counter value, and 4 bits for the backoff */ +#define ADAPTIVE_BACKOFF_BITS 4 +/* The initial counter value is 31 == 2**ADAPTIVE_BACKOFF_START - 1 */ +#define ADAPTIVE_BACKOFF_START 5 + +#define MAX_BACKOFF_VALUE (16 - ADAPTIVE_BACKOFF_BITS) + + +static inline uint16_t +adaptive_counter_bits(int value, int backoff) { + return (value << ADAPTIVE_BACKOFF_BITS) | + (backoff & ((1< MAX_BACKOFF_VALUE) { + backoff = MAX_BACKOFF_VALUE; + } + unsigned int value = (1 << backoff) - 1; + return adaptive_counter_bits(value, backoff); +} + + +/* Line array cache for tracing */ + +extern int _PyCode_CreateLineArray(PyCodeObject *co); + +static inline int +_PyCode_InitLineArray(PyCodeObject *co) +{ + if (co->_co_linearray) { + return 0; + } + return _PyCode_CreateLineArray(co); +} + +static inline int +_PyCode_LineNumberFromArray(PyCodeObject *co, int index) +{ + assert(co->_co_linearray != NULL); + assert(index >= 0); + assert(index < Py_SIZE(co)); + if (co->_co_linearray_entry_size == 2) { + return ((int16_t *)co->_co_linearray)[index]; + } + else { + assert(co->_co_linearray_entry_size == 4); + return ((int32_t *)co->_co_linearray)[index]; + } +} #ifdef __cplusplus diff --git a/include/internal/pycore_condvar.h b/include/internal/pycore_condvar.h index 8b89d709..981c962b 100644 --- a/include/internal/pycore_condvar.h +++ b/include/internal/pycore_condvar.h @@ -20,7 +20,9 @@ */ #define Py_HAVE_CONDVAR -#include +#ifdef HAVE_PTHREAD_H +# include +#endif #define PyMUTEX_T pthread_mutex_t #define PyCOND_T pthread_cond_t @@ -60,7 +62,7 @@ typedef CRITICAL_SECTION PyMUTEX_T; with a Semaphore. Semaphores are available on Windows XP (2003 server) and later. We use a Semaphore rather than an auto-reset event, because although - an auto-resent event might appear to solve the lost-wakeup bug (race + an auto-reset event might appear to solve the lost-wakeup bug (race condition between releasing the outer lock and waiting) because it maintains state even though a wait hasn't happened, there is still a lost wakeup problem if more than one thread are interrupted in the diff --git a/include/internal/pycore_context.h b/include/internal/pycore_context.h index a482dd42..1bf4e8f3 100644 --- a/include/internal/pycore_context.h +++ b/include/internal/pycore_context.h @@ -7,6 +7,34 @@ #include "pycore_hamt.h" /* PyHamtObject */ + +extern PyTypeObject _PyContextTokenMissing_Type; + +/* runtime lifecycle */ + +PyStatus _PyContext_Init(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 +64,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 new file mode 100644 index 00000000..dc308fe5 --- /dev/null +++ b/include/internal/pycore_dict.h @@ -0,0 +1,178 @@ + +#ifndef Py_INTERNAL_DICT_H +#define Py_INTERNAL_DICT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#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; + PyObject *me_key; + PyObject *me_value; /* This field is only meaningful for combined tables */ +} PyDictKeyEntry; + +typedef struct { + PyObject *me_key; /* The key must be Unicode and have hash. */ + PyObject *me_value; /* This field is only meaningful for combined tables */ +} PyDictUnicodeEntry; + +extern PyDictKeysObject *_PyDict_NewKeysForClass(void); +extern PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *); + +/* Gets a version number unique to the current state of the keys of dict, if possible. + * Returns the version number, or zero if it was not possible to get a version number. */ +extern uint32_t _PyDictKeys_GetVersionForCurrentState(PyDictKeysObject *dictkeys); + +extern Py_ssize_t _PyDict_KeysSize(PyDictKeysObject *keys); + +/* _Py_dict_lookup() returns index of entry which can be used like DK_ENTRIES(dk)[index]. + * -1 when no entry found, -3 when compare raises error. + */ +extern Py_ssize_t _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr); + +extern Py_ssize_t _PyDict_GetItemHint(PyDictObject *, PyObject *, Py_ssize_t, PyObject **); +extern Py_ssize_t _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject *key); +extern PyObject *_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObject *); + +/* Consumes references to key and value */ +extern int _PyDict_SetItem_Take2(PyDictObject *op, PyObject *key, PyObject *value); +extern int _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr, PyObject *name, PyObject *value); + +extern PyObject *_PyDict_Pop_KnownHash(PyObject *, PyObject *, Py_hash_t, PyObject *); + +#define DKIX_EMPTY (-1) +#define DKIX_DUMMY (-2) /* Used internally */ +#define DKIX_ERROR (-3) +#define DKIX_KEY_CHANGED (-4) /* Used internally */ + +typedef enum { + DICT_KEYS_GENERAL = 0, + DICT_KEYS_UNICODE = 1, + DICT_KEYS_SPLIT = 2 +} DictKeysKind; + +/* See dictobject.c for actual layout of DictKeysObject */ +struct _dictkeysobject { + Py_ssize_t dk_refcnt; + + /* Size of the hash table (dk_indices). It must be a power of 2. */ + uint8_t dk_log2_size; + + /* Size of the hash table (dk_indices) by bytes. */ + uint8_t dk_log2_index_bytes; + + /* Kind of keys */ + uint8_t dk_kind; + + /* Version number -- Reset to 0 by any modification to keys */ + uint32_t dk_version; + + /* Number of usable entries in dk_entries. */ + Py_ssize_t dk_usable; + + /* Number of used entries in dk_entries. */ + Py_ssize_t dk_nentries; + + /* Actual hash table of dk_size entries. It holds indices in dk_entries, + or DKIX_EMPTY(-1) or DKIX_DUMMY(-2). + + Indices must be: 0 <= indice < USABLE_FRACTION(dk_size). + + The size in bytes of an indice depends on dk_size: + + - 1 byte if dk_size <= 0xff (char*) + - 2 bytes if dk_size <= 0xffff (int16_t*) + - 4 bytes if dk_size <= 0xffffffff (int32_t*) + - 8 bytes otherwise (int64_t*) + + Dynamically sized, SIZEOF_VOID_P is minimum. */ + char dk_indices[]; /* char is required to avoid strict aliasing. */ + + /* "PyDictKeyEntry or PyDictUnicodeEntry dk_entries[USABLE_FRACTION(DK_SIZE(dk))];" array follows: + see the DK_ENTRIES() macro */ +}; + +/* This must be no more than 250, for the prefix size to fit in one byte. */ +#define SHARED_KEYS_MAX_SIZE 30 +#define NEXT_LOG2_SHARED_KEYS_MAX_SIZE 6 + +/* Layout of dict values: + * + * The PyObject *values are preceded by an array of bytes holding + * the insertion order and size. + * [-1] = prefix size. [-2] = used size. size[-2-n...] = insertion order. + */ +struct _dictvalues { + PyObject *values[1]; +}; + +#define DK_LOG_SIZE(dk) ((dk)->dk_log2_size) +#if SIZEOF_VOID_P > 4 +#define DK_SIZE(dk) (((int64_t)1)<dk_kind == DICT_KEYS_GENERAL), (PyDictKeyEntry*)(&((int8_t*)((dk)->dk_indices))[(size_t)1 << (dk)->dk_log2_index_bytes])) +#define DK_UNICODE_ENTRIES(dk) \ + (assert(dk->dk_kind != DICT_KEYS_GENERAL), (PyDictUnicodeEntry*)(&((int8_t*)((dk)->dk_indices))[(size_t)1 << (dk)->dk_log2_index_bytes])) +#define DK_IS_UNICODE(dk) ((dk)->dk_kind != DICT_KEYS_GENERAL) + +extern uint64_t _pydict_global_version; + +#define DICT_NEXT_VERSION() (++_pydict_global_version) + +extern PyObject *_PyObject_MakeDictFromInstanceAttributes(PyObject *obj, PyDictValues *values); +extern PyObject *_PyDict_FromItems( + PyObject *const *keys, Py_ssize_t keys_offset, + PyObject *const *values, Py_ssize_t values_offset, + Py_ssize_t length); + +static inline void +_PyDictValues_AddToInsertionOrder(PyDictValues *values, Py_ssize_t ix) +{ + assert(ix < SHARED_KEYS_MAX_SIZE); + uint8_t *size_ptr = ((uint8_t *)values)-2; + int size = *size_ptr; + assert(size+2 < ((uint8_t *)values)[-1]); + size++; + size_ptr[-size] = (uint8_t)ix; + *size_ptr = size; +} + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_DICT_H */ diff --git a/include/internal/pycore_dtoa.h b/include/internal/pycore_dtoa.h index 3faf8cf6..c77cf6e4 100644 --- a/include/internal/pycore_dtoa.h +++ b/include/internal/pycore_dtoa.h @@ -1,4 +1,3 @@ -#ifndef PY_NO_SHORT_FLOAT_REPR #ifdef __cplusplus extern "C" { #endif @@ -7,6 +6,11 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR + + +#if _PY_SHORT_FLOAT_REPR == 1 + /* These functions are used by modules compiled as C extension like math: they must be exported. */ @@ -17,7 +21,8 @@ PyAPI_FUNC(void) _Py_dg_freedtoa(char *s); PyAPI_FUNC(double) _Py_dg_stdnan(int sign); PyAPI_FUNC(double) _Py_dg_infinity(int sign); +#endif // _PY_SHORT_FLOAT_REPR == 1 + #ifdef __cplusplus } #endif -#endif /* !PY_NO_SHORT_FLOAT_REPR */ diff --git a/include/internal/pycore_emscripten_signal.h b/include/internal/pycore_emscripten_signal.h new file mode 100644 index 00000000..8b3287d8 --- /dev/null +++ b/include/internal/pycore_emscripten_signal.h @@ -0,0 +1,25 @@ +#ifndef Py_EMSCRIPTEN_SIGNAL_H +#define Py_EMSCRIPTEN_SIGNAL_H + +#if defined(__EMSCRIPTEN__) + +void +_Py_CheckEmscriptenSignals(void); + +void +_Py_CheckEmscriptenSignalsPeriodically(void); + +#define _Py_CHECK_EMSCRIPTEN_SIGNALS() _Py_CheckEmscriptenSignals() + +#define _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY() _Py_CheckEmscriptenSignalsPeriodically() + +extern int Py_EMSCRIPTEN_SIGNAL_HANDLING; + +#else + +#define _Py_CHECK_EMSCRIPTEN_SIGNALS() +#define _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY() + +#endif // defined(__EMSCRIPTEN__) + +#endif // ndef Py_EMSCRIPTEN_SIGNAL_H diff --git a/include/internal/pycore_exceptions.h b/include/internal/pycore_exceptions.h new file mode 100644 index 00000000..4a9df709 --- /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 int _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_fileutils.h b/include/internal/pycore_fileutils.h index c1c9244a..3ce8108e 100644 --- a/include/internal/pycore_fileutils.h +++ b/include/internal/pycore_fileutils.h @@ -10,6 +10,171 @@ extern "C" { #include /* struct lconv */ +typedef enum { + _Py_ERROR_UNKNOWN=0, + _Py_ERROR_STRICT, + _Py_ERROR_SURROGATEESCAPE, + _Py_ERROR_REPLACE, + _Py_ERROR_IGNORE, + _Py_ERROR_BACKSLASHREPLACE, + _Py_ERROR_SURROGATEPASS, + _Py_ERROR_XMLCHARREFREPLACE, + _Py_ERROR_OTHER +} _Py_error_handler; + +PyAPI_FUNC(_Py_error_handler) _Py_GetErrorHandler(const char *errors); + +PyAPI_FUNC(int) _Py_DecodeLocaleEx( + const char *arg, + wchar_t **wstr, + size_t *wlen, + const char **reason, + int current_locale, + _Py_error_handler errors); + +PyAPI_FUNC(int) _Py_EncodeLocaleEx( + const wchar_t *text, + char **str, + size_t *error_pos, + const char **reason, + int current_locale, + _Py_error_handler errors); + +PyAPI_FUNC(char*) _Py_EncodeLocaleRaw( + const wchar_t *text, + size_t *error_pos); + +PyAPI_FUNC(PyObject *) _Py_device_encoding(int); + +#if defined(MS_WINDOWS) || defined(__APPLE__) + /* On Windows, the count parameter of read() is an int (bpo-9015, bpo-9611). + On macOS 10.13, read() and write() with more than INT_MAX bytes + fail with EINVAL (bpo-24658). */ +# define _PY_READ_MAX INT_MAX +# define _PY_WRITE_MAX INT_MAX +#else + /* write() should truncate the input to PY_SSIZE_T_MAX bytes, + but it's safer to do it ourself to have a portable behaviour */ +# define _PY_READ_MAX PY_SSIZE_T_MAX +# define _PY_WRITE_MAX PY_SSIZE_T_MAX +#endif + +#ifdef MS_WINDOWS +struct _Py_stat_struct { + unsigned long st_dev; + uint64_t st_ino; + unsigned short st_mode; + int st_nlink; + int st_uid; + int st_gid; + unsigned long st_rdev; + __int64 st_size; + time_t st_atime; + int st_atime_nsec; + time_t st_mtime; + int st_mtime_nsec; + time_t st_ctime; + int st_ctime_nsec; + unsigned long st_file_attributes; + unsigned long st_reparse_tag; +}; +#else +# define _Py_stat_struct stat +#endif + +PyAPI_FUNC(int) _Py_fstat( + int fd, + struct _Py_stat_struct *status); + +PyAPI_FUNC(int) _Py_fstat_noraise( + int fd, + struct _Py_stat_struct *status); + +PyAPI_FUNC(int) _Py_stat( + PyObject *path, + struct stat *status); + +PyAPI_FUNC(int) _Py_open( + const char *pathname, + int flags); + +PyAPI_FUNC(int) _Py_open_noraise( + const char *pathname, + int flags); + +PyAPI_FUNC(FILE *) _Py_wfopen( + const wchar_t *path, + const wchar_t *mode); + +PyAPI_FUNC(Py_ssize_t) _Py_read( + int fd, + void *buf, + size_t count); + +PyAPI_FUNC(Py_ssize_t) _Py_write( + int fd, + const void *buf, + size_t count); + +PyAPI_FUNC(Py_ssize_t) _Py_write_noraise( + int fd, + const void *buf, + size_t count); + +#ifdef HAVE_READLINK +PyAPI_FUNC(int) _Py_wreadlink( + const wchar_t *path, + wchar_t *buf, + /* Number of characters of 'buf' buffer + including the trailing NUL character */ + size_t buflen); +#endif + +#ifdef HAVE_REALPATH +PyAPI_FUNC(wchar_t*) _Py_wrealpath( + const wchar_t *path, + wchar_t *resolved_path, + /* Number of characters of 'resolved_path' buffer + including the trailing NUL character */ + size_t resolved_path_len); +#endif + +PyAPI_FUNC(wchar_t*) _Py_wgetcwd( + wchar_t *buf, + /* Number of characters of 'buf' buffer + including the trailing NUL character */ + size_t buflen); + +PyAPI_FUNC(int) _Py_get_inheritable(int fd); + +PyAPI_FUNC(int) _Py_set_inheritable(int fd, int inheritable, + int *atomic_flag_works); + +PyAPI_FUNC(int) _Py_set_inheritable_async_safe(int fd, int inheritable, + int *atomic_flag_works); + +PyAPI_FUNC(int) _Py_dup(int fd); + +#ifndef MS_WINDOWS +PyAPI_FUNC(int) _Py_get_blocking(int fd); + +PyAPI_FUNC(int) _Py_set_blocking(int fd, int blocking); +#else /* MS_WINDOWS */ +PyAPI_FUNC(void*) _Py_get_osfhandle_noraise(int fd); + +PyAPI_FUNC(void*) _Py_get_osfhandle(int fd); + +PyAPI_FUNC(int) _Py_open_osfhandle_noraise(void *handle, int flags); + +PyAPI_FUNC(int) _Py_open_osfhandle(void *handle, int flags); +#endif /* MS_WINDOWS */ + +// This is used after getting NULL back from Py_DecodeLocale(). +#define DECODE_LOCALE_ERR(NAME, LEN) \ + ((LEN) == (size_t)-2) \ + ? _PyStatus_ERR("cannot decode " NAME) \ + : _PyStatus_NO_MEMORY() + PyAPI_DATA(int) _Py_HasFileSystemDefaultEncodeErrors; PyAPI_FUNC(int) _Py_DecodeUTF8Ex( @@ -33,6 +198,9 @@ PyAPI_FUNC(wchar_t*) _Py_DecodeUTF8_surrogateescape( Py_ssize_t arglen, size_t *wlen); +extern int +_Py_wstat(const wchar_t *, struct stat *); + PyAPI_FUNC(int) _Py_GetForceASCII(void); /* Reset "force ASCII" mode (if it was initialized). @@ -65,6 +233,42 @@ extern int _Py_EncodeNonUnicodeWchar_InPlace( Py_ssize_t size); #endif +extern int _Py_isabs(const wchar_t *path); +extern int _Py_abspath(const wchar_t *path, wchar_t **abspath_p); +#ifdef MS_WINDOWS +extern int _PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p); +#endif +extern wchar_t * _Py_join_relfile(const wchar_t *dirname, + const wchar_t *relfile); +extern int _Py_add_relfile(wchar_t *dirname, + const wchar_t *relfile, + size_t bufsize); +extern size_t _Py_find_basename(const wchar_t *filename); +PyAPI_FUNC(wchar_t *) _Py_normpath(wchar_t *path, Py_ssize_t size); + + +// Macros to protect CRT calls against instant termination when passed an +// invalid parameter (bpo-23524). IPH stands for Invalid Parameter Handler. +// Usage: +// +// _Py_BEGIN_SUPPRESS_IPH +// ... +// _Py_END_SUPPRESS_IPH +#if defined _MSC_VER && _MSC_VER >= 1900 + +# include // _set_thread_local_invalid_parameter_handler() + + extern _invalid_parameter_handler _Py_silent_invalid_parameter_handler; +# define _Py_BEGIN_SUPPRESS_IPH \ + { _invalid_parameter_handler _Py_old_handler = \ + _set_thread_local_invalid_parameter_handler(_Py_silent_invalid_parameter_handler); +# define _Py_END_SUPPRESS_IPH \ + _set_thread_local_invalid_parameter_handler(_Py_old_handler); } +#else +# define _Py_BEGIN_SUPPRESS_IPH +# define _Py_END_SUPPRESS_IPH +#endif /* _MSC_VER >= 1900 */ + #ifdef __cplusplus } #endif diff --git a/include/internal/pycore_floatobject.h b/include/internal/pycore_floatobject.h new file mode 100644 index 00000000..8a655543 --- /dev/null +++ b/include/internal/pycore_floatobject.h @@ -0,0 +1,59 @@ +#ifndef Py_INTERNAL_FLOATOBJECT_H +#define Py_INTERNAL_FLOATOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# 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 *); +extern void _PyFloat_FiniType(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 +}; + +void _PyFloat_ExactDealloc(PyObject *op); + + +PyAPI_FUNC(void) _PyFloat_DebugMallocStats(FILE* out); + + +/* Format the object based on the format_spec, as defined in PEP 3101 + (Advanced String Formatting). */ +PyAPI_FUNC(int) _PyFloat_FormatAdvancedWriter( + _PyUnicodeWriter *writer, + PyObject *obj, + PyObject *format_spec, + Py_ssize_t start, + Py_ssize_t end); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_FLOATOBJECT_H */ diff --git a/include/internal/pycore_format.h b/include/internal/pycore_format.h index 1b8d5753..1899609e 100644 --- a/include/internal/pycore_format.h +++ b/include/internal/pycore_format.h @@ -14,12 +14,14 @@ extern "C" { * F_BLANK ' ' * F_ALT '#' * F_ZERO '0' + * F_NO_NEG_0 'z' */ #define F_LJUST (1<<0) #define F_SIGN (1<<1) #define F_BLANK (1<<2) #define F_ALT (1<<3) #define F_ZERO (1<<4) +#define F_NO_NEG_0 (1<<5) #ifdef __cplusplus } diff --git a/include/internal/pycore_frame.h b/include/internal/pycore_frame.h new file mode 100644 index 00000000..ecc8346f --- /dev/null +++ b/include/internal/pycore_frame.h @@ -0,0 +1,237 @@ +#ifndef Py_INTERNAL_FRAME_H +#define Py_INTERNAL_FRAME_H +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* See Objects/frame_layout.md for an explanation of the frame stack + * including explanation of the PyFrameObject and _PyInterpreterFrame + * structs. */ + + +struct _frame { + PyObject_HEAD + PyFrameObject *f_back; /* previous frame, or NULL */ + struct _PyInterpreterFrame *f_frame; /* points to the frame data */ + PyObject *f_trace; /* Trace function */ + int f_lineno; /* Current line number. Only valid if non-zero */ + char f_trace_lines; /* Emit per-line trace events? */ + char f_trace_opcodes; /* Emit per-opcode trace events? */ + char f_fast_as_locals; /* Have the fast locals of this frame been converted to a dict? */ + /* The frame data, if this frame object owns the frame */ + PyObject *_f_frame_data[1]; +}; + +extern PyFrameObject* _PyFrame_New_NoTrack(PyCodeObject *code); + + +/* other API */ + +typedef enum _framestate { + FRAME_CREATED = -2, + FRAME_SUSPENDED = -1, + FRAME_EXECUTING = 0, + FRAME_COMPLETED = 1, + FRAME_CLEARED = 4 +} PyFrameState; + +enum _frameowner { + FRAME_OWNED_BY_THREAD = 0, + FRAME_OWNED_BY_GENERATOR = 1, + FRAME_OWNED_BY_FRAME_OBJECT = 2 +}; + +typedef struct _PyInterpreterFrame { + /* "Specials" section */ + PyFunctionObject *f_func; /* Strong reference */ + PyObject *f_globals; /* Borrowed reference */ + PyObject *f_builtins; /* Borrowed reference */ + PyObject *f_locals; /* Strong reference, may be NULL */ + PyCodeObject *f_code; /* Strong reference */ + PyFrameObject *frame_obj; /* Strong reference, may be NULL */ + /* Linkage section */ + struct _PyInterpreterFrame *previous; + // NOTE: This is not necessarily the last instruction started in the given + // frame. Rather, it is the code unit *prior to* the *next* instruction. For + // example, it may be an inline CACHE entry, an instruction we just jumped + // over, or (in the case of a newly-created frame) a totally invalid value: + _Py_CODEUNIT *prev_instr; + int stacktop; /* Offset of TOS from localsplus */ + bool is_entry; // Whether this is the "root" frame for the current _PyCFrame. + char owner; + /* Locals and stack */ + PyObject *localsplus[1]; +} _PyInterpreterFrame; + +#define _PyInterpreterFrame_LASTI(IF) \ + ((int)((IF)->prev_instr - _PyCode_CODE((IF)->f_code))) + +static inline PyObject **_PyFrame_Stackbase(_PyInterpreterFrame *f) { + return f->localsplus + f->f_code->co_nlocalsplus; +} + +static inline PyObject *_PyFrame_StackPeek(_PyInterpreterFrame *f) { + assert(f->stacktop > f->f_code->co_nlocalsplus); + assert(f->localsplus[f->stacktop-1] != NULL); + return f->localsplus[f->stacktop-1]; +} + +static inline PyObject *_PyFrame_StackPop(_PyInterpreterFrame *f) { + assert(f->stacktop > f->f_code->co_nlocalsplus); + f->stacktop--; + return f->localsplus[f->stacktop]; +} + +static inline void _PyFrame_StackPush(_PyInterpreterFrame *f, PyObject *value) { + f->localsplus[f->stacktop] = value; + f->stacktop++; +} + +#define FRAME_SPECIALS_SIZE ((sizeof(_PyInterpreterFrame)-1)/sizeof(PyObject *)) + +void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest); + +/* Consumes reference to func */ +static inline void +_PyFrame_InitializeSpecials( + _PyInterpreterFrame *frame, PyFunctionObject *func, + PyObject *locals, int nlocalsplus) +{ + frame->f_func = func; + frame->f_code = (PyCodeObject *)Py_NewRef(func->func_code); + frame->f_builtins = func->func_builtins; + frame->f_globals = func->func_globals; + frame->f_locals = Py_XNewRef(locals); + frame->stacktop = nlocalsplus; + frame->frame_obj = NULL; + frame->prev_instr = _PyCode_CODE(frame->f_code) - 1; + frame->is_entry = false; + frame->owner = FRAME_OWNED_BY_THREAD; +} + +/* Gets the pointer to the locals array + * that precedes this frame. + */ +static inline PyObject** +_PyFrame_GetLocalsArray(_PyInterpreterFrame *frame) +{ + return frame->localsplus; +} + +static inline PyObject** +_PyFrame_GetStackPointer(_PyInterpreterFrame *frame) +{ + return frame->localsplus+frame->stacktop; +} + +static inline void +_PyFrame_SetStackPointer(_PyInterpreterFrame *frame, PyObject **stack_pointer) +{ + frame->stacktop = (int)(stack_pointer - frame->localsplus); +} + +/* Determine whether a frame is incomplete. + * A frame is incomplete if it is part way through + * creating cell objects or a generator or coroutine. + * + * Frames on the frame stack are incomplete until the + * first RESUME instruction. + * Frames owned by a generator are always complete. + */ +static inline bool +_PyFrame_IsIncomplete(_PyInterpreterFrame *frame) +{ + return frame->owner != FRAME_OWNED_BY_GENERATOR && + frame->prev_instr < _PyCode_CODE(frame->f_code) + frame->f_code->_co_firsttraceable; +} + +/* For use by _PyFrame_GetFrameObject + Do not call directly. */ +PyFrameObject * +_PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame); + +/* Gets the PyFrameObject for this frame, lazily + * creating it if necessary. + * Returns a borrowed referennce */ +static inline PyFrameObject * +_PyFrame_GetFrameObject(_PyInterpreterFrame *frame) +{ + + assert(!_PyFrame_IsIncomplete(frame)); + PyFrameObject *res = frame->frame_obj; + if (res != NULL) { + return res; + } + return _PyFrame_MakeAndSetFrameObject(frame); +} + +/* Clears all references in the frame. + * If take is non-zero, then the _PyInterpreterFrame frame + * may be transferred to the frame object it references + * instead of being cleared. Either way + * the caller no longer owns the references + * in the frame. + * take should be set to 1 for heap allocated + * frames like the ones in generators and coroutines. + */ +void +_PyFrame_Clear(_PyInterpreterFrame * frame); + +int +_PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg); + +int +_PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame); + +void +_PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear); + +extern _PyInterpreterFrame * +_PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size); + +static inline bool +_PyThreadState_HasStackSpace(PyThreadState *tstate, size_t size) +{ + assert( + (tstate->datastack_top == NULL && tstate->datastack_limit == NULL) + || + (tstate->datastack_top != NULL && tstate->datastack_limit != NULL) + ); + return tstate->datastack_top != NULL && + size < (size_t)(tstate->datastack_limit - tstate->datastack_top); +} + +static inline _PyInterpreterFrame * +_PyThreadState_BumpFramePointer(PyThreadState *tstate, size_t size) +{ + if (_PyThreadState_HasStackSpace(tstate, size)) { + _PyInterpreterFrame *res = (_PyInterpreterFrame *)tstate->datastack_top; + tstate->datastack_top += size; + return res; + } + return _PyThreadState_BumpFramePointerSlow(tstate, size); +} + +void _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame *frame); + +/* Consume reference to func */ +_PyInterpreterFrame * +_PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func); + +int _PyInterpreterFrame_GetLine(_PyInterpreterFrame *frame); + +static inline +PyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame) +{ + assert(frame->owner == FRAME_OWNED_BY_GENERATOR); + size_t offset_in_gen = offsetof(PyGenObject, gi_iframe); + return (PyGenObject *)(((char *)frame) - offset_in_gen); +} + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_FRAME_H */ diff --git a/include/internal/pycore_function.h b/include/internal/pycore_function.h new file mode 100644 index 00000000..1c87aa31 --- /dev/null +++ b/include/internal/pycore_function.h @@ -0,0 +1,18 @@ +#ifndef Py_INTERNAL_FUNCTION_H +#define Py_INTERNAL_FUNCTION_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +extern PyFunctionObject* _PyFunction_FromConstructor(PyFrameConstructor *constr); + +extern uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_FUNCTION_H */ diff --git a/include/internal/pycore_gc.h b/include/internal/pycore_gc.h index 9db4a471..16c18936 100644 --- a/include/internal/pycore_gc.h +++ b/include/internal/pycore_gc.h @@ -20,6 +20,7 @@ typedef struct { } PyGC_Head; #define _Py_AS_GC(o) ((PyGC_Head *)(o)-1) +#define _PyGC_Head_UNUSED PyGC_Head /* True if the object is currently tracked by the GC. */ #define _PyObject_GC_IS_TRACKED(o) (_Py_AS_GC(o)->_gc_next != 0) @@ -43,7 +44,7 @@ typedef struct { // Lowest bit of _gc_next is used for flags only in GC. // But it is always 0 for normal code. #define _PyGCHead_NEXT(g) ((PyGC_Head*)(g)->_gc_next) -#define _PyGCHead_SET_NEXT(g, p) ((g)->_gc_next = (uintptr_t)(p)) +#define _PyGCHead_SET_NEXT(g, p) _Py_RVALUE((g)->_gc_next = (uintptr_t)(p)) // Lowest two bits of _gc_prev is used for _PyGC_PREV_MASK_* flags. #define _PyGCHead_PREV(g) ((PyGC_Head*)((g)->_gc_prev & _PyGC_PREV_MASK)) @@ -56,7 +57,7 @@ typedef struct { #define _PyGCHead_FINALIZED(g) \ (((g)->_gc_prev & _PyGC_PREV_MASK_FINALIZED) != 0) #define _PyGCHead_SET_FINALIZED(g) \ - ((g)->_gc_prev |= _PyGC_PREV_MASK_FINALIZED) + _Py_RVALUE((g)->_gc_prev |= _PyGC_PREV_MASK_FINALIZED) #define _PyGC_FINALIZED(o) \ _PyGCHead_FINALIZED(_Py_AS_GC(o)) @@ -134,6 +135,7 @@ struct _gc_runtime_state { /* Current call-stack depth of tp_dealloc calls. */ int trash_delete_nesting; + /* Is automatic collection enabled? */ int enabled; int debug; /* linked lists of container objects */ @@ -161,13 +163,13 @@ struct _gc_runtime_state { Py_ssize_t long_lived_pending; }; + extern void _PyGC_InitState(struct _gc_runtime_state *); extern Py_ssize_t _PyGC_CollectNoFail(PyThreadState *tstate); // Functions to clear types free lists -extern void _PyFrame_ClearFreeList(PyInterpreterState *interp); extern void _PyTuple_ClearFreeList(PyInterpreterState *interp); extern void _PyFloat_ClearFreeList(PyInterpreterState *interp); extern void _PyList_ClearFreeList(PyInterpreterState *interp); diff --git a/include/internal/pycore_genobject.h b/include/internal/pycore_genobject.h new file mode 100644 index 00000000..42db0d87 --- /dev/null +++ b/include/internal/pycore_genobject.h @@ -0,0 +1,49 @@ +#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 + +extern PyObject *_PyGen_yf(PyGenObject *); +extern PyObject *_PyCoro_GetAwaitableIter(PyObject *o); +extern PyObject *_PyAsyncGenValueWrapperNew(PyObject *); + +/* 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_global_objects.h b/include/internal/pycore_global_objects.h new file mode 100644 index 00000000..98673d4e --- /dev/null +++ b/include/internal/pycore_global_objects.h @@ -0,0 +1,54 @@ +#ifndef Py_INTERNAL_GLOBAL_OBJECTS_H +#define Py_INTERNAL_GLOBAL_OBJECTS_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include "pycore_gc.h" // PyGC_Head +#include "pycore_global_strings.h" // struct _Py_global_strings + + +// These would be in pycore_long.h if it weren't for an include cycle. +#define _PY_NSMALLPOSINTS 257 +#define _PY_NSMALLNEGINTS 5 + + +// Only immutable objects should be considered runtime-global. +// All others must be per-interpreter. + +#define _Py_GLOBAL_OBJECT(NAME) \ + _PyRuntime.global_objects.NAME +#define _Py_SINGLETON(NAME) \ + _Py_GLOBAL_OBJECT(singletons.NAME) + +struct _Py_global_objects { + struct { + /* 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 (exclusive). + */ + PyLongObject small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS]; + + PyBytesObject bytes_empty; + struct { + PyBytesObject ob; + char eos; + } bytes_characters[256]; + + struct _Py_global_strings strings; + + _PyGC_Head_UNUSED _tuple_empty_gc_not_used; + PyTupleObject tuple_empty; + } singletons; +}; + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_GLOBAL_OBJECTS_H */ diff --git a/include/internal/pycore_global_strings.h b/include/internal/pycore_global_strings.h new file mode 100644 index 00000000..ca970627 --- /dev/null +++ b/include/internal/pycore_global_strings.h @@ -0,0 +1,395 @@ +#ifndef Py_INTERNAL_GLOBAL_STRINGS_H +#define Py_INTERNAL_GLOBAL_STRINGS_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +// The data structure & init here are inspired by Tools/scripts/deepfreeze.py. + +// All field names generated by ASCII_STR() have a common prefix, +// to help avoid collisions with keywords, etc. + +#define STRUCT_FOR_ASCII_STR(LITERAL) \ + struct { \ + PyASCIIObject _ascii; \ + uint8_t _data[sizeof(LITERAL)]; \ + } +#define STRUCT_FOR_STR(NAME, LITERAL) \ + STRUCT_FOR_ASCII_STR(LITERAL) _ ## NAME; +#define STRUCT_FOR_ID(NAME) \ + STRUCT_FOR_ASCII_STR(#NAME) _ ## NAME; + +// XXX Order by frequency of use? + +/* The following is auto-generated by Tools/scripts/generate_global_objects.py. */ +struct _Py_global_strings { + struct { + STRUCT_FOR_STR(anon_dictcomp, "") + STRUCT_FOR_STR(anon_genexpr, "") + STRUCT_FOR_STR(anon_lambda, "") + STRUCT_FOR_STR(anon_listcomp, "") + STRUCT_FOR_STR(anon_module, "") + STRUCT_FOR_STR(anon_setcomp, "") + STRUCT_FOR_STR(anon_string, "") + STRUCT_FOR_STR(anon_unknown, "") + STRUCT_FOR_STR(close_br, "}") + STRUCT_FOR_STR(comma_sep, ", ") + STRUCT_FOR_STR(dbl_close_br, "}}") + STRUCT_FOR_STR(dbl_open_br, "{{") + STRUCT_FOR_STR(dbl_percent, "%%") + STRUCT_FOR_STR(dot, ".") + STRUCT_FOR_STR(dot_locals, ".") + STRUCT_FOR_STR(empty, "") + STRUCT_FOR_STR(list_err, "list index out of range") + STRUCT_FOR_STR(newline, "\n") + STRUCT_FOR_STR(open_br, "{") + STRUCT_FOR_STR(percent, "%") + STRUCT_FOR_STR(utf_8, "utf-8") + } literals; + + struct { + STRUCT_FOR_ID(False) + STRUCT_FOR_ID(Py_Repr) + STRUCT_FOR_ID(TextIOWrapper) + STRUCT_FOR_ID(True) + STRUCT_FOR_ID(WarningMessage) + STRUCT_FOR_ID(_) + STRUCT_FOR_ID(__IOBase_closed) + STRUCT_FOR_ID(__abc_tpflags__) + STRUCT_FOR_ID(__abs__) + STRUCT_FOR_ID(__abstractmethods__) + STRUCT_FOR_ID(__add__) + STRUCT_FOR_ID(__aenter__) + STRUCT_FOR_ID(__aexit__) + STRUCT_FOR_ID(__aiter__) + STRUCT_FOR_ID(__all__) + STRUCT_FOR_ID(__and__) + STRUCT_FOR_ID(__anext__) + STRUCT_FOR_ID(__annotations__) + STRUCT_FOR_ID(__args__) + STRUCT_FOR_ID(__await__) + STRUCT_FOR_ID(__bases__) + STRUCT_FOR_ID(__bool__) + STRUCT_FOR_ID(__build_class__) + STRUCT_FOR_ID(__builtins__) + STRUCT_FOR_ID(__bytes__) + STRUCT_FOR_ID(__call__) + STRUCT_FOR_ID(__cantrace__) + STRUCT_FOR_ID(__class__) + STRUCT_FOR_ID(__class_getitem__) + STRUCT_FOR_ID(__classcell__) + STRUCT_FOR_ID(__complex__) + STRUCT_FOR_ID(__contains__) + STRUCT_FOR_ID(__copy__) + STRUCT_FOR_ID(__del__) + STRUCT_FOR_ID(__delattr__) + STRUCT_FOR_ID(__delete__) + STRUCT_FOR_ID(__delitem__) + STRUCT_FOR_ID(__dict__) + STRUCT_FOR_ID(__dir__) + STRUCT_FOR_ID(__divmod__) + STRUCT_FOR_ID(__doc__) + STRUCT_FOR_ID(__enter__) + STRUCT_FOR_ID(__eq__) + STRUCT_FOR_ID(__exit__) + STRUCT_FOR_ID(__file__) + STRUCT_FOR_ID(__float__) + STRUCT_FOR_ID(__floordiv__) + STRUCT_FOR_ID(__format__) + STRUCT_FOR_ID(__fspath__) + STRUCT_FOR_ID(__ge__) + STRUCT_FOR_ID(__get__) + STRUCT_FOR_ID(__getattr__) + STRUCT_FOR_ID(__getattribute__) + STRUCT_FOR_ID(__getinitargs__) + STRUCT_FOR_ID(__getitem__) + STRUCT_FOR_ID(__getnewargs__) + STRUCT_FOR_ID(__getnewargs_ex__) + STRUCT_FOR_ID(__getstate__) + STRUCT_FOR_ID(__gt__) + STRUCT_FOR_ID(__hash__) + STRUCT_FOR_ID(__iadd__) + STRUCT_FOR_ID(__iand__) + STRUCT_FOR_ID(__ifloordiv__) + STRUCT_FOR_ID(__ilshift__) + STRUCT_FOR_ID(__imatmul__) + STRUCT_FOR_ID(__imod__) + STRUCT_FOR_ID(__import__) + STRUCT_FOR_ID(__imul__) + STRUCT_FOR_ID(__index__) + STRUCT_FOR_ID(__init__) + STRUCT_FOR_ID(__init_subclass__) + STRUCT_FOR_ID(__instancecheck__) + STRUCT_FOR_ID(__int__) + STRUCT_FOR_ID(__invert__) + STRUCT_FOR_ID(__ior__) + STRUCT_FOR_ID(__ipow__) + STRUCT_FOR_ID(__irshift__) + STRUCT_FOR_ID(__isabstractmethod__) + STRUCT_FOR_ID(__isub__) + STRUCT_FOR_ID(__iter__) + STRUCT_FOR_ID(__itruediv__) + STRUCT_FOR_ID(__ixor__) + STRUCT_FOR_ID(__le__) + STRUCT_FOR_ID(__len__) + STRUCT_FOR_ID(__length_hint__) + STRUCT_FOR_ID(__lltrace__) + STRUCT_FOR_ID(__loader__) + STRUCT_FOR_ID(__lshift__) + STRUCT_FOR_ID(__lt__) + STRUCT_FOR_ID(__main__) + STRUCT_FOR_ID(__matmul__) + STRUCT_FOR_ID(__missing__) + STRUCT_FOR_ID(__mod__) + STRUCT_FOR_ID(__module__) + STRUCT_FOR_ID(__mro_entries__) + STRUCT_FOR_ID(__mul__) + STRUCT_FOR_ID(__name__) + STRUCT_FOR_ID(__ne__) + STRUCT_FOR_ID(__neg__) + STRUCT_FOR_ID(__new__) + STRUCT_FOR_ID(__newobj__) + STRUCT_FOR_ID(__newobj_ex__) + STRUCT_FOR_ID(__next__) + STRUCT_FOR_ID(__notes__) + STRUCT_FOR_ID(__or__) + STRUCT_FOR_ID(__orig_class__) + STRUCT_FOR_ID(__origin__) + STRUCT_FOR_ID(__package__) + STRUCT_FOR_ID(__parameters__) + STRUCT_FOR_ID(__path__) + STRUCT_FOR_ID(__pos__) + STRUCT_FOR_ID(__pow__) + STRUCT_FOR_ID(__prepare__) + STRUCT_FOR_ID(__qualname__) + STRUCT_FOR_ID(__radd__) + STRUCT_FOR_ID(__rand__) + STRUCT_FOR_ID(__rdivmod__) + STRUCT_FOR_ID(__reduce__) + STRUCT_FOR_ID(__reduce_ex__) + STRUCT_FOR_ID(__repr__) + STRUCT_FOR_ID(__reversed__) + STRUCT_FOR_ID(__rfloordiv__) + STRUCT_FOR_ID(__rlshift__) + STRUCT_FOR_ID(__rmatmul__) + STRUCT_FOR_ID(__rmod__) + STRUCT_FOR_ID(__rmul__) + STRUCT_FOR_ID(__ror__) + STRUCT_FOR_ID(__round__) + STRUCT_FOR_ID(__rpow__) + STRUCT_FOR_ID(__rrshift__) + STRUCT_FOR_ID(__rshift__) + STRUCT_FOR_ID(__rsub__) + STRUCT_FOR_ID(__rtruediv__) + STRUCT_FOR_ID(__rxor__) + STRUCT_FOR_ID(__set__) + STRUCT_FOR_ID(__set_name__) + STRUCT_FOR_ID(__setattr__) + STRUCT_FOR_ID(__setitem__) + STRUCT_FOR_ID(__setstate__) + STRUCT_FOR_ID(__sizeof__) + STRUCT_FOR_ID(__slotnames__) + STRUCT_FOR_ID(__slots__) + STRUCT_FOR_ID(__spec__) + STRUCT_FOR_ID(__str__) + STRUCT_FOR_ID(__sub__) + STRUCT_FOR_ID(__subclasscheck__) + STRUCT_FOR_ID(__subclasshook__) + STRUCT_FOR_ID(__truediv__) + STRUCT_FOR_ID(__trunc__) + STRUCT_FOR_ID(__typing_is_unpacked_typevartuple__) + STRUCT_FOR_ID(__typing_prepare_subst__) + STRUCT_FOR_ID(__typing_subst__) + STRUCT_FOR_ID(__typing_unpacked_tuple_args__) + STRUCT_FOR_ID(__warningregistry__) + STRUCT_FOR_ID(__weakref__) + STRUCT_FOR_ID(__xor__) + STRUCT_FOR_ID(_abc_impl) + STRUCT_FOR_ID(_annotation) + STRUCT_FOR_ID(_blksize) + STRUCT_FOR_ID(_bootstrap) + STRUCT_FOR_ID(_dealloc_warn) + STRUCT_FOR_ID(_finalizing) + STRUCT_FOR_ID(_find_and_load) + STRUCT_FOR_ID(_fix_up_module) + STRUCT_FOR_ID(_get_sourcefile) + STRUCT_FOR_ID(_handle_fromlist) + STRUCT_FOR_ID(_initializing) + STRUCT_FOR_ID(_is_text_encoding) + STRUCT_FOR_ID(_lock_unlock_module) + STRUCT_FOR_ID(_showwarnmsg) + STRUCT_FOR_ID(_shutdown) + STRUCT_FOR_ID(_slotnames) + STRUCT_FOR_ID(_strptime_time) + STRUCT_FOR_ID(_uninitialized_submodules) + STRUCT_FOR_ID(_warn_unawaited_coroutine) + STRUCT_FOR_ID(_xoptions) + STRUCT_FOR_ID(add) + STRUCT_FOR_ID(append) + STRUCT_FOR_ID(big) + STRUCT_FOR_ID(buffer) + STRUCT_FOR_ID(builtins) + STRUCT_FOR_ID(c_call) + STRUCT_FOR_ID(c_exception) + STRUCT_FOR_ID(c_return) + STRUCT_FOR_ID(call) + STRUCT_FOR_ID(clear) + STRUCT_FOR_ID(close) + STRUCT_FOR_ID(closed) + STRUCT_FOR_ID(code) + STRUCT_FOR_ID(copy) + STRUCT_FOR_ID(copyreg) + STRUCT_FOR_ID(decode) + STRUCT_FOR_ID(default) + STRUCT_FOR_ID(defaultaction) + STRUCT_FOR_ID(dictcomp) + STRUCT_FOR_ID(difference_update) + STRUCT_FOR_ID(dispatch_table) + STRUCT_FOR_ID(displayhook) + STRUCT_FOR_ID(enable) + STRUCT_FOR_ID(encode) + STRUCT_FOR_ID(encoding) + STRUCT_FOR_ID(end_lineno) + STRUCT_FOR_ID(end_offset) + STRUCT_FOR_ID(errors) + STRUCT_FOR_ID(excepthook) + STRUCT_FOR_ID(exception) + STRUCT_FOR_ID(extend) + STRUCT_FOR_ID(filename) + STRUCT_FOR_ID(fileno) + STRUCT_FOR_ID(fillvalue) + STRUCT_FOR_ID(filters) + STRUCT_FOR_ID(find_class) + STRUCT_FOR_ID(flush) + STRUCT_FOR_ID(genexpr) + STRUCT_FOR_ID(get) + STRUCT_FOR_ID(get_source) + STRUCT_FOR_ID(getattr) + STRUCT_FOR_ID(getstate) + STRUCT_FOR_ID(ignore) + STRUCT_FOR_ID(importlib) + STRUCT_FOR_ID(inf) + STRUCT_FOR_ID(intersection) + STRUCT_FOR_ID(isatty) + STRUCT_FOR_ID(isinstance) + STRUCT_FOR_ID(items) + STRUCT_FOR_ID(iter) + STRUCT_FOR_ID(join) + STRUCT_FOR_ID(keys) + STRUCT_FOR_ID(lambda) + STRUCT_FOR_ID(last_traceback) + STRUCT_FOR_ID(last_type) + STRUCT_FOR_ID(last_value) + STRUCT_FOR_ID(latin1) + STRUCT_FOR_ID(len) + STRUCT_FOR_ID(line) + STRUCT_FOR_ID(lineno) + STRUCT_FOR_ID(listcomp) + STRUCT_FOR_ID(little) + STRUCT_FOR_ID(locale) + STRUCT_FOR_ID(match) + STRUCT_FOR_ID(metaclass) + STRUCT_FOR_ID(mode) + STRUCT_FOR_ID(modules) + STRUCT_FOR_ID(mro) + STRUCT_FOR_ID(msg) + STRUCT_FOR_ID(n_fields) + STRUCT_FOR_ID(n_sequence_fields) + STRUCT_FOR_ID(n_unnamed_fields) + STRUCT_FOR_ID(name) + STRUCT_FOR_ID(newlines) + STRUCT_FOR_ID(next) + STRUCT_FOR_ID(obj) + STRUCT_FOR_ID(offset) + STRUCT_FOR_ID(onceregistry) + STRUCT_FOR_ID(opcode) + STRUCT_FOR_ID(open) + STRUCT_FOR_ID(parent) + STRUCT_FOR_ID(partial) + STRUCT_FOR_ID(path) + STRUCT_FOR_ID(peek) + STRUCT_FOR_ID(persistent_id) + STRUCT_FOR_ID(persistent_load) + STRUCT_FOR_ID(print_file_and_line) + STRUCT_FOR_ID(ps1) + STRUCT_FOR_ID(ps2) + STRUCT_FOR_ID(raw) + STRUCT_FOR_ID(read) + STRUCT_FOR_ID(read1) + STRUCT_FOR_ID(readable) + STRUCT_FOR_ID(readall) + STRUCT_FOR_ID(readinto) + STRUCT_FOR_ID(readinto1) + STRUCT_FOR_ID(readline) + STRUCT_FOR_ID(reducer_override) + STRUCT_FOR_ID(reload) + STRUCT_FOR_ID(replace) + STRUCT_FOR_ID(reset) + STRUCT_FOR_ID(return) + STRUCT_FOR_ID(reversed) + STRUCT_FOR_ID(seek) + STRUCT_FOR_ID(seekable) + STRUCT_FOR_ID(send) + STRUCT_FOR_ID(setcomp) + STRUCT_FOR_ID(setstate) + STRUCT_FOR_ID(sort) + STRUCT_FOR_ID(stderr) + STRUCT_FOR_ID(stdin) + STRUCT_FOR_ID(stdout) + STRUCT_FOR_ID(strict) + STRUCT_FOR_ID(symmetric_difference_update) + STRUCT_FOR_ID(tell) + STRUCT_FOR_ID(text) + STRUCT_FOR_ID(threading) + STRUCT_FOR_ID(throw) + STRUCT_FOR_ID(top) + STRUCT_FOR_ID(truncate) + STRUCT_FOR_ID(unraisablehook) + STRUCT_FOR_ID(values) + STRUCT_FOR_ID(version) + STRUCT_FOR_ID(warnings) + STRUCT_FOR_ID(warnoptions) + STRUCT_FOR_ID(writable) + STRUCT_FOR_ID(write) + STRUCT_FOR_ID(zipimporter) + } identifiers; + struct { + PyASCIIObject _ascii; + uint8_t _data[2]; + } ascii[128]; + struct { + PyCompactUnicodeObject _latin1; + uint8_t _data[2]; + } latin1[128]; +}; +/* End auto-generated code */ + +#undef ID +#undef STR + + +#define _Py_ID(NAME) \ + (_Py_SINGLETON(strings.identifiers._ ## NAME._ascii.ob_base)) +#define _Py_STR(NAME) \ + (_Py_SINGLETON(strings.literals._ ## NAME._ascii.ob_base)) + +/* _Py_DECLARE_STR() should precede all uses of _Py_STR() in a function. + + This is true even if the same string has already been declared + elsewhere, even in the same file. Mismatched duplicates are detected + by Tools/scripts/generate-global-objects.py. + + Pairing _Py_DECLARE_STR() with every use of _Py_STR() makes sure the + string keeps working even if the declaration is removed somewhere + else. It also makes it clear what the actual string is at every + place it is being used. */ +#define _Py_DECLARE_STR(name, str) + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_GLOBAL_STRINGS_H */ diff --git a/include/internal/pycore_hamt.h b/include/internal/pycore_hamt.h index 357d9661..4d64288b 100644 --- a/include/internal/pycore_hamt.h +++ b/include/internal/pycore_hamt.h @@ -20,6 +20,21 @@ This constant is used to define a datastucture for storing iteration state. #define _Py_HAMT_MAX_TREE_DEPTH 8 +extern PyTypeObject _PyHamt_Type; +extern PyTypeObject _PyHamt_ArrayNode_Type; +extern PyTypeObject _PyHamt_BitmapNode_Type; +extern PyTypeObject _PyHamt_CollisionNode_Type; +extern PyTypeObject _PyHamtKeys_Type; +extern PyTypeObject _PyHamtValues_Type; +extern PyTypeObject _PyHamtItems_Type; + +/* runtime lifecycle */ + +void _PyHamt_Fini(PyInterpreterState *); + + +/* other API */ + #define PyHamt_Check(o) Py_IS_TYPE(o, &_PyHamt_Type) @@ -73,15 +88,6 @@ typedef struct { } PyHamtIterator; -PyAPI_DATA(PyTypeObject) _PyHamt_Type; -PyAPI_DATA(PyTypeObject) _PyHamt_ArrayNode_Type; -PyAPI_DATA(PyTypeObject) _PyHamt_BitmapNode_Type; -PyAPI_DATA(PyTypeObject) _PyHamt_CollisionNode_Type; -PyAPI_DATA(PyTypeObject) _PyHamtKeys_Type; -PyAPI_DATA(PyTypeObject) _PyHamtValues_Type; -PyAPI_DATA(PyTypeObject) _PyHamtItems_Type; - - /* Create a new HAMT immutable mapping. */ PyHamtObject * _PyHamt_New(void); @@ -122,7 +128,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_import.h b/include/internal/pycore_import.h index e21ed0a7..aee1f66a 100644 --- a/include/internal/pycore_import.h +++ b/include/internal/pycore_import.h @@ -10,6 +10,16 @@ extern PyStatus _PyImport_ReInitLock(void); #endif extern PyObject* _PyImport_BootstrapImp(PyThreadState *tstate); +struct _module_alias { + const char *name; /* ASCII encoded string */ + const char *orig; /* ASCII encoded string */ +}; + +PyAPI_DATA(const struct _frozen *) _PyImport_FrozenBootstrap; +PyAPI_DATA(const struct _frozen *) _PyImport_FrozenStdlib; +PyAPI_DATA(const struct _frozen *) _PyImport_FrozenTest; +extern const struct _module_alias * _PyImport_FrozenAliases; + #ifdef __cplusplus } #endif diff --git a/include/internal/pycore_initconfig.h b/include/internal/pycore_initconfig.h index 21c71bfa..d765600f 100644 --- a/include/internal/pycore_initconfig.h +++ b/include/internal/pycore_initconfig.h @@ -155,6 +155,7 @@ extern PyStatus _PyConfig_Copy( extern PyStatus _PyConfig_InitPathConfig( PyConfig *config, int compute_path_config); +extern PyStatus _PyConfig_InitImportConfig(PyConfig *config); extern PyStatus _PyConfig_Read(PyConfig *config, int compute_path_config); extern PyStatus _PyConfig_Write(const PyConfig *config, struct pyruntimestate *runtime); @@ -165,6 +166,10 @@ extern PyStatus _PyConfig_SetPyArgv( PyAPI_FUNC(PyObject*) _PyConfig_AsDict(const PyConfig *config); PyAPI_FUNC(int) _PyConfig_FromDict(PyConfig *config, PyObject *dict); +extern void _Py_DumpPathConfig(PyThreadState *tstate); + +PyAPI_FUNC(PyObject*) _Py_Get_Getpath_CodeObject(void); + extern int _Py_global_config_int_max_str_digits; diff --git a/include/internal/pycore_interp.h b/include/internal/pycore_interp.h index a564b125..02d25d67 100644 --- a/include/internal/pycore_interp.h +++ b/include/internal/pycore_interp.h @@ -8,10 +8,22 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include + #include "pycore_atomic.h" // _Py_atomic_address #include "pycore_ast_state.h" // struct ast_state +#include "pycore_code.h" // struct callable_cache +#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 { @@ -39,129 +51,6 @@ struct _ceval_state { /* Request for dropping the GIL */ _Py_atomic_int gil_drop_request; struct _pending_calls pending; -#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS - struct _gil_runtime_state gil; -#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; - - // Unused member kept for ABI backward compatibility with Python 3.10.0: - // see bpo-46006. - PyObject *unused_interned; - - // Unicode identifiers (_Py_Identifier): see _PyUnicode_FromId() - struct _Py_unicode_ids ids; -}; - -struct _Py_float_state { - /* 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; -}; - -/* 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 { - PyListObject *free_list[PyList_MAXFREELIST]; - int numfree; -}; - -#ifndef PyDict_MAXFREELIST -# define PyDict_MAXFREELIST 80 -#endif - -struct _Py_dict_state { - /* 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; -}; - -struct _Py_frame_state { - PyFrameObject *free_list; - /* number of frames currently in free_list */ - int numfree; -}; - -#ifndef _PyAsyncGen_MAXFREELIST -# define _PyAsyncGen_MAXFREELIST 80 -#endif - -struct _Py_async_gen_state { - /* 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; -}; - -struct _Py_context_state { - // List of free PyContext objects - PyContext *freelist; - int numfree; -}; - -struct _Py_exc_state { - // The dict mapping from errno codes to OSError subclasses - PyObject *errnomap; - PyBaseExceptionObject *memerrors_freelist; - int memerrors_numfree; }; @@ -179,42 +68,29 @@ 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 */ -#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 +/* PyInterpreterState holds the global state for one of the runtime's + interpreters. Typically the initial (main) interpreter is the only one. -// The PyInterpreterState typedef is in Include/pystate.h. + The PyInterpreterState typedef is in Include/pystate.h. + */ struct _is { - struct _is *next; - struct _ts *tstate_head; + PyInterpreterState *next; + + struct pythreads { + uint64_t next_unique_id; + /* The linked list of threads, newest first. */ + PyThreadState *head; + /* Used in Modules/_threadmodule.c. */ + long count; + /* Support for runtime thread stack size tuning. + A value of 0 means using the platform's default stack size + or the size specified by the THREAD_STACK_SIZE macro. */ + /* Used in Python/thread.c. */ + size_t stacksize; + } threads; /* Reference to the _PyRuntime global variable. This field exists to not have to pass runtime in addition to tstate to a function. @@ -226,8 +102,16 @@ struct _is { int requires_idref; PyThread_type_lock id_mutex; + /* Has been initialized to a safe state. + + In order to be effective, this must be set to 0 during or right + after allocation. */ + int _initialized; int finalizing; + /* Was this interpreter statically allocated? */ + bool _static; + struct _ceval_state ceval; struct _gc_runtime_state gc; @@ -240,14 +124,9 @@ struct _is { PyObject *builtins; // importlib module PyObject *importlib; - - /* Used in Modules/_threadmodule.c. */ - long num_threads; - /* Support for runtime thread stack size tuning. - A value of 0 means using the platform's default stack size - or the size specified by the THREAD_STACK_SIZE macro. */ - /* Used in Python/thread.c. */ - size_t pythread_stacksize; + // override for config->use_frozen_modules (for tests) + // (-1: "off", 1: "on", 0: no override) + int override_frozen_modules; PyObject *codec_search_path; PyObject *codec_search_cache; @@ -275,20 +154,11 @@ struct _is { PyObject *after_forkers_child; #endif - uint64_t tstate_next_unique_id; - struct _warnings_runtime_state warnings; struct atexit_state atexit; PyObject *audit_hooks; - /* 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_bytes_state bytes; struct _Py_unicode_state unicode; struct _Py_float_state float_state; /* Using a cache is very effective since typically only a single slice is @@ -298,17 +168,35 @@ struct _is { struct _Py_tuple_state tuple; struct _Py_list_state list; struct _Py_dict_state dict_state; - struct _Py_frame_state frame; struct _Py_async_gen_state async_gen; struct _Py_context_state context; struct _Py_exc_state exc_state; struct ast_state ast; struct type_cache type_cache; + struct callable_cache callable_cache; int int_max_str_digits; + + /* The following fields are here to avoid allocation during init. + The data is exposed through PyInterpreterState pointer fields. + These fields should not be accessed directly outside of init. + + All other PyInterpreterState pointer fields are populated when + needed and default to NULL. + + For now there are some exceptions to that rule, which require + allocation during init. These will be addressed on a case-by-case + basis. Also see _PyRuntimeState regarding the various mutex fields. + */ + + /* the initial PyInterpreterState.threads.head */ + PyThreadState _initial_thread; }; + +/* other API */ + extern void _PyInterpreterState_ClearModules(PyInterpreterState *interp); extern void _PyInterpreterState_Clear(PyThreadState *tstate); @@ -327,11 +215,11 @@ struct _xidregitem { struct _xidregitem *next; }; -PyAPI_FUNC(struct _is*) _PyInterpreterState_LookUpID(int64_t); +PyAPI_FUNC(PyInterpreterState*) _PyInterpreterState_LookUpID(int64_t); -PyAPI_FUNC(int) _PyInterpreterState_IDInitref(struct _is *); -PyAPI_FUNC(int) _PyInterpreterState_IDIncref(struct _is *); -PyAPI_FUNC(void) _PyInterpreterState_IDDecref(struct _is *); +PyAPI_FUNC(int) _PyInterpreterState_IDInitref(PyInterpreterState *); +PyAPI_FUNC(int) _PyInterpreterState_IDIncref(PyInterpreterState *); +PyAPI_FUNC(void) _PyInterpreterState_IDDecref(PyInterpreterState *); #ifdef __cplusplus } diff --git a/include/cpython/interpreteridobject.h b/include/internal/pycore_interpreteridobject.h similarity index 51% rename from include/cpython/interpreteridobject.h rename to include/internal/pycore_interpreteridobject.h index 50765842..804831e7 100644 --- a/include/cpython/interpreteridobject.h +++ b/include/internal/pycore_interpreteridobject.h @@ -1,11 +1,22 @@ -#ifndef Py_CPYTHON_INTERPRETERIDOBJECT_H -# error "this header file must not be included directly" +/* Interpreter ID Object */ + +#ifndef Py_INTERNAL_INTERPRETERIDOBJECT_H +#define Py_INTERNAL_INTERPRETERIDOBJECT_H +#ifdef __cplusplus +extern "C" { #endif -/* Interpreter ID Object */ +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif PyAPI_DATA(PyTypeObject) _PyInterpreterID_Type; PyAPI_FUNC(PyObject *) _PyInterpreterID_New(int64_t); PyAPI_FUNC(PyObject *) _PyInterpreterState_GetIDObject(PyInterpreterState *); PyAPI_FUNC(PyInterpreterState *) _PyInterpreterID_LookUp(PyObject *); + +#ifdef __cplusplus +} +#endif +#endif // !Py_INTERNAL_INTERPRETERIDOBJECT_H diff --git a/include/internal/pycore_list.h b/include/internal/pycore_list.h index f18fb052..860dce1f 100644 --- a/include/internal/pycore_list.h +++ b/include/internal/pycore_list.h @@ -11,8 +11,50 @@ 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) +extern int +_PyList_AppendTakeRefListResize(PyListObject *self, PyObject *newitem); + +static inline int +_PyList_AppendTakeRef(PyListObject *self, PyObject *newitem) +{ + assert(self != NULL && newitem != NULL); + assert(PyList_Check(self)); + Py_ssize_t len = PyList_GET_SIZE(self); + Py_ssize_t allocated = self->allocated; + assert((size_t)len + 1 < PY_SSIZE_T_MAX); + if (allocated > len) { + PyList_SET_ITEM(self, len, newitem); + Py_SET_SIZE(self, len + 1); + return 0; + } + return _PyList_AppendTakeRefListResize(self, newitem); +} #ifdef __cplusplus } diff --git a/include/internal/pycore_long.h b/include/internal/pycore_long.h index 90069f8e..0f466eb6 100644 --- a/include/internal/pycore_long.h +++ b/include/internal/pycore_long.h @@ -8,8 +8,8 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_interp.h" // PyInterpreterState.small_ints -#include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_global_objects.h" // _PY_NSMALLNEGINTS +#include "pycore_runtime.h" // _PyRuntime /* * Default int base conversion size limitation: Denial of Service prevention. @@ -46,28 +46,67 @@ extern "C" { # error "_PY_LONG_DEFAULT_MAX_STR_DIGITS smaller than threshold." #endif -// Don't call this function but _PyLong_GetZero() and _PyLong_GetOne() -static inline PyObject* __PyLong_GetSmallInt_internal(int value) -{ - PyInterpreterState *interp = _PyInterpreterState_GET(); - assert(-_PY_NSMALLNEGINTS <= value && value < _PY_NSMALLPOSINTS); - size_t index = _PY_NSMALLNEGINTS + value; - PyObject *obj = (PyObject*)interp->small_ints[index]; - // _PyLong_GetZero(), _PyLong_GetOne() and get_small_int() must not be - // called before _PyLong_Init() nor after _PyLong_Fini(). - assert(obj != NULL); - return obj; -} + +/* runtime lifecycle */ + +extern PyStatus _PyLong_InitTypes(PyInterpreterState *); +extern void _PyLong_FiniTypes(PyInterpreterState *interp); + + +/* other API */ + +#define _PyLong_SMALL_INTS _Py_SINGLETON(small_ints) + +// _PyLong_GetZero() and _PyLong_GetOne() must always be available +// _PyLong_FromUnsignedChar must always be available +#if _PY_NSMALLPOSINTS < 257 +# error "_PY_NSMALLPOSINTS must be greater than or equal to 257" +#endif // Return a borrowed reference to the zero singleton. // The function cannot return NULL. static inline PyObject* _PyLong_GetZero(void) -{ return __PyLong_GetSmallInt_internal(0); } +{ 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 __PyLong_GetSmallInt_internal(1); } +{ return (PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+1]; } + +static inline PyObject* _PyLong_FromUnsignedChar(unsigned char i) +{ + return Py_NewRef((PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+i]); +} + +PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right); +PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right); +PyObject *_PyLong_Subtract(PyLongObject *left, PyLongObject *right); + +/* Used by Python/mystrtoul.c, _PyBytes_FromHex(), + _PyBytes_DecodeEscape(), etc. */ +PyAPI_DATA(unsigned char) _PyLong_DigitValue[256]; + +/* Format the object based on the format_spec, as defined in PEP 3101 + (Advanced String Formatting). */ +PyAPI_FUNC(int) _PyLong_FormatAdvancedWriter( + _PyUnicodeWriter *writer, + PyObject *obj, + PyObject *format_spec, + Py_ssize_t start, + Py_ssize_t end); + +PyAPI_FUNC(int) _PyLong_FormatWriter( + _PyUnicodeWriter *writer, + PyObject *obj, + int base, + int alternate); + +PyAPI_FUNC(char*) _PyLong_FormatBytesWriter( + _PyBytesWriter *writer, + char *str, + PyObject *obj, + int base, + int alternate); #ifdef __cplusplus } diff --git a/include/internal/pycore_moduleobject.h b/include/internal/pycore_moduleobject.h index e9978abd..76361b8d 100644 --- a/include/internal/pycore_moduleobject.h +++ b/include/internal/pycore_moduleobject.h @@ -11,7 +11,7 @@ extern "C" { typedef struct { PyObject_HEAD PyObject *md_dict; - struct PyModuleDef *md_def; + PyModuleDef *md_def; void *md_state; PyObject *md_weaklist; // for logging purposes after md_dict is cleared diff --git a/include/internal/pycore_namespace.h b/include/internal/pycore_namespace.h new file mode 100644 index 00000000..cb76f040 --- /dev/null +++ b/include/internal/pycore_namespace.h @@ -0,0 +1,20 @@ +// Simple namespace object interface + +#ifndef Py_INTERNAL_NAMESPACE_H +#define Py_INTERNAL_NAMESPACE_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +PyAPI_DATA(PyTypeObject) _PyNamespace_Type; + +PyAPI_FUNC(PyObject *) _PyNamespace_New(PyObject *kwds); + +#ifdef __cplusplus +} +#endif +#endif // !Py_INTERNAL_NAMESPACE_H diff --git a/include/internal/pycore_object.h b/include/internal/pycore_object.h index 90d98134..f022f824 100644 --- a/include/internal/pycore_object.h +++ b/include/internal/pycore_object.h @@ -8,9 +8,59 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include #include "pycore_gc.h" // _PyObject_GC_IS_TRACKED() #include "pycore_interp.h" // PyInterpreterState.gc #include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "pycore_runtime.h" // _PyRuntime + +#define _PyObject_IMMORTAL_INIT(type) \ + { \ + .ob_refcnt = 999999999, \ + .ob_type = type, \ + } +#define _PyVarObject_IMMORTAL_INIT(type, size) \ + { \ + .ob_base = _PyObject_IMMORTAL_INIT(type), \ + .ob_size = size, \ + } + +PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc( + const char *func, + const char *message); + +#define _Py_FatalRefcountError(message) _Py_FatalRefcountErrorFunc(__func__, message) + +static inline void +_Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct) +{ +#ifdef Py_REF_DEBUG + _Py_RefTotal--; +#endif + if (--op->ob_refcnt != 0) { + assert(op->ob_refcnt > 0); + } + else { +#ifdef Py_TRACE_REFS + _Py_ForgetReference(op); +#endif + destruct(op); + } +} + +static inline void +_Py_DECREF_NO_DEALLOC(PyObject *op) +{ +#ifdef Py_REF_DEBUG + _Py_RefTotal--; +#endif + op->ob_refcnt--; +#ifdef Py_DEBUG + if (op->ob_refcnt <= 0) { + _Py_FatalRefcountError("Expected a positive remaining refcount"); + } +#endif +} PyAPI_FUNC(int) _PyType_CheckConsistency(PyTypeObject *type); PyAPI_FUNC(int) _PyDict_CheckConsistency(PyObject *mp, int check_content); @@ -29,8 +79,6 @@ _PyType_HasFeature(PyTypeObject *type, unsigned long feature) { extern void _PyType_InitCache(PyInterpreterState *interp); -/* Only private in Python 3.10 and 3.9.8+; public in 3.11 */ -extern PyObject *_PyType_GetQualName(PyTypeObject *type); /* Inline functions trading binary compatibility for speed: _PyObject_Init() is the fast version of PyObject_Init(), and @@ -170,6 +218,15 @@ _PyObject_IS_GC(PyObject *obj) // Fast inlined version of PyType_IS_GC() #define _PyType_IS_GC(t) _PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC) +static inline size_t +_PyType_PreHeaderSize(PyTypeObject *tp) +{ + return _PyType_IS_GC(tp) * sizeof(PyGC_Head) + + _PyType_HasFeature(tp, Py_TPFLAGS_MANAGED_DICT) * 2 * sizeof(PyObject *); +} + +void _PyObject_GC_Link(PyObject *op); + // Usage: assert(_Py_CheckSlotResult(obj, "__getitem__", result != NULL)); extern int _Py_CheckSlotResult( PyObject *obj, @@ -180,6 +237,73 @@ extern int _Py_CheckSlotResult( // See also the Py_TPFLAGS_READY flag. #define _PyType_IsReady(type) ((type)->tp_dict != NULL) +// Test if a type supports weak references +static inline int _PyType_SUPPORTS_WEAKREFS(PyTypeObject *type) { + return (type->tp_weaklistoffset > 0); +} + +extern PyObject* _PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems); + +extern int _PyObject_InitializeDict(PyObject *obj); +extern int _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, + PyObject *name, PyObject *value); +PyObject * _PyObject_GetInstanceAttribute(PyObject *obj, PyDictValues *values, + PyObject *name); + +static inline PyDictValues **_PyObject_ValuesPointer(PyObject *obj) +{ + assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT); + return ((PyDictValues **)obj)-4; +} + +static inline PyObject **_PyObject_ManagedDictPointer(PyObject *obj) +{ + assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT); + return ((PyObject **)obj)-3; +} + +#define MANAGED_DICT_OFFSET (((int)sizeof(PyObject *))*-3) + +extern PyObject ** _PyObject_DictPointer(PyObject *); +extern int _PyObject_VisitInstanceAttributes(PyObject *self, visitproc visit, void *arg); +extern void _PyObject_ClearInstanceAttributes(PyObject *self); +extern void _PyObject_FreeInstanceAttributes(PyObject *self); +extern int _PyObject_IsInstanceDictEmpty(PyObject *); +extern PyObject* _PyType_GetSubclasses(PyTypeObject *); + +// Access macro to the members which are floating "behind" the object +#define _PyHeapType_GET_MEMBERS(etype) \ + ((PyMemberDef *)(((char *)etype) + Py_TYPE(etype)->tp_basicsize)) + +PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, PyObject *); + +/* C function call trampolines to mitigate bad function pointer casts. + * + * Typical native ABIs ignore additional arguments or fill in missing + * values with 0/NULL in function pointer cast. Compilers do not show + * warnings when a function pointer is explicitly casted to an + * incompatible type. + * + * Bad fpcasts are an issue in WebAssembly. WASM's indirect_call has strict + * function signature checks. Argument count, types, and return type must + * match. + * + * Third party code unintentionally rely on problematic fpcasts. The call + * trampoline mitigates common occurences of bad fpcasts on Emscripten. + */ +#if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE) +#define _PyCFunction_TrampolineCall(meth, self, args) \ + _PyCFunctionWithKeywords_TrampolineCall( \ + (*(PyCFunctionWithKeywords)(void(*)(void))meth), self, args, NULL) +extern PyObject* _PyCFunctionWithKeywords_TrampolineCall( + PyCFunctionWithKeywords meth, PyObject *, PyObject *, PyObject *); +#else +#define _PyCFunction_TrampolineCall(meth, self, args) \ + (meth)((self), (args)) +#define _PyCFunctionWithKeywords_TrampolineCall(meth, self, args, kw) \ + (meth)((self), (args), (kw)) +#endif // __EMSCRIPTEN__ && PY_CALL_TRAMPOLINE + #ifdef __cplusplus } #endif diff --git a/include/internal/pycore_opcode.h b/include/internal/pycore_opcode.h new file mode 100644 index 00000000..eadcba1a --- /dev/null +++ b/include/internal/pycore_opcode.h @@ -0,0 +1,581 @@ +// Auto-generated by Tools/scripts/generate_opcode_h.py from Lib/opcode.py + +#ifndef Py_INTERNAL_OPCODE_H +#define Py_INTERNAL_OPCODE_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include "opcode.h" + +extern const uint8_t _PyOpcode_Caches[256]; + +extern const uint8_t _PyOpcode_Deopt[256]; + +#ifdef NEED_OPCODE_TABLES +static const uint32_t _PyOpcode_RelativeJump[8] = { + 0U, + 0U, + 536870912U, + 135118848U, + 4163U, + 122880U, + 0U, + 0U, +}; +static const uint32_t _PyOpcode_Jump[8] = { + 0U, + 0U, + 536870912U, + 135118848U, + 4163U, + 122880U, + 0U, + 0U, +}; + +const uint8_t _PyOpcode_Caches[256] = { + [BINARY_SUBSCR] = 4, + [STORE_SUBSCR] = 1, + [UNPACK_SEQUENCE] = 1, + [STORE_ATTR] = 4, + [LOAD_ATTR] = 4, + [COMPARE_OP] = 2, + [LOAD_GLOBAL] = 5, + [BINARY_OP] = 1, + [LOAD_METHOD] = 10, + [PRECALL] = 1, + [CALL] = 4, +}; + +const uint8_t _PyOpcode_Deopt[256] = { + [ASYNC_GEN_WRAP] = ASYNC_GEN_WRAP, + [BEFORE_ASYNC_WITH] = BEFORE_ASYNC_WITH, + [BEFORE_WITH] = BEFORE_WITH, + [BINARY_OP] = BINARY_OP, + [BINARY_OP_ADAPTIVE] = BINARY_OP, + [BINARY_OP_ADD_FLOAT] = BINARY_OP, + [BINARY_OP_ADD_INT] = BINARY_OP, + [BINARY_OP_ADD_UNICODE] = BINARY_OP, + [BINARY_OP_INPLACE_ADD_UNICODE] = BINARY_OP, + [BINARY_OP_MULTIPLY_FLOAT] = BINARY_OP, + [BINARY_OP_MULTIPLY_INT] = BINARY_OP, + [BINARY_OP_SUBTRACT_FLOAT] = BINARY_OP, + [BINARY_OP_SUBTRACT_INT] = BINARY_OP, + [BINARY_SUBSCR] = BINARY_SUBSCR, + [BINARY_SUBSCR_ADAPTIVE] = BINARY_SUBSCR, + [BINARY_SUBSCR_DICT] = BINARY_SUBSCR, + [BINARY_SUBSCR_GETITEM] = BINARY_SUBSCR, + [BINARY_SUBSCR_LIST_INT] = BINARY_SUBSCR, + [BINARY_SUBSCR_TUPLE_INT] = BINARY_SUBSCR, + [BUILD_CONST_KEY_MAP] = BUILD_CONST_KEY_MAP, + [BUILD_LIST] = BUILD_LIST, + [BUILD_MAP] = BUILD_MAP, + [BUILD_SET] = BUILD_SET, + [BUILD_SLICE] = BUILD_SLICE, + [BUILD_STRING] = BUILD_STRING, + [BUILD_TUPLE] = BUILD_TUPLE, + [CACHE] = CACHE, + [CALL] = CALL, + [CALL_ADAPTIVE] = CALL, + [CALL_FUNCTION_EX] = CALL_FUNCTION_EX, + [CALL_PY_EXACT_ARGS] = CALL, + [CALL_PY_WITH_DEFAULTS] = CALL, + [CHECK_EG_MATCH] = CHECK_EG_MATCH, + [CHECK_EXC_MATCH] = CHECK_EXC_MATCH, + [COMPARE_OP] = COMPARE_OP, + [COMPARE_OP_ADAPTIVE] = COMPARE_OP, + [COMPARE_OP_FLOAT_JUMP] = COMPARE_OP, + [COMPARE_OP_INT_JUMP] = COMPARE_OP, + [COMPARE_OP_STR_JUMP] = COMPARE_OP, + [CONTAINS_OP] = CONTAINS_OP, + [COPY] = COPY, + [COPY_FREE_VARS] = COPY_FREE_VARS, + [DELETE_ATTR] = DELETE_ATTR, + [DELETE_DEREF] = DELETE_DEREF, + [DELETE_FAST] = DELETE_FAST, + [DELETE_GLOBAL] = DELETE_GLOBAL, + [DELETE_NAME] = DELETE_NAME, + [DELETE_SUBSCR] = DELETE_SUBSCR, + [DICT_MERGE] = DICT_MERGE, + [DICT_UPDATE] = DICT_UPDATE, + [END_ASYNC_FOR] = END_ASYNC_FOR, + [EXTENDED_ARG] = EXTENDED_ARG, + [EXTENDED_ARG_QUICK] = EXTENDED_ARG, + [FORMAT_VALUE] = FORMAT_VALUE, + [FOR_ITER] = FOR_ITER, + [GET_AITER] = GET_AITER, + [GET_ANEXT] = GET_ANEXT, + [GET_AWAITABLE] = GET_AWAITABLE, + [GET_ITER] = GET_ITER, + [GET_LEN] = GET_LEN, + [GET_YIELD_FROM_ITER] = GET_YIELD_FROM_ITER, + [IMPORT_FROM] = IMPORT_FROM, + [IMPORT_NAME] = IMPORT_NAME, + [IMPORT_STAR] = IMPORT_STAR, + [IS_OP] = IS_OP, + [JUMP_BACKWARD] = JUMP_BACKWARD, + [JUMP_BACKWARD_NO_INTERRUPT] = JUMP_BACKWARD_NO_INTERRUPT, + [JUMP_BACKWARD_QUICK] = JUMP_BACKWARD, + [JUMP_FORWARD] = JUMP_FORWARD, + [JUMP_IF_FALSE_OR_POP] = JUMP_IF_FALSE_OR_POP, + [JUMP_IF_TRUE_OR_POP] = JUMP_IF_TRUE_OR_POP, + [KW_NAMES] = KW_NAMES, + [LIST_APPEND] = LIST_APPEND, + [LIST_EXTEND] = LIST_EXTEND, + [LIST_TO_TUPLE] = LIST_TO_TUPLE, + [LOAD_ASSERTION_ERROR] = LOAD_ASSERTION_ERROR, + [LOAD_ATTR] = LOAD_ATTR, + [LOAD_ATTR_ADAPTIVE] = LOAD_ATTR, + [LOAD_ATTR_INSTANCE_VALUE] = LOAD_ATTR, + [LOAD_ATTR_MODULE] = LOAD_ATTR, + [LOAD_ATTR_SLOT] = LOAD_ATTR, + [LOAD_ATTR_WITH_HINT] = LOAD_ATTR, + [LOAD_BUILD_CLASS] = LOAD_BUILD_CLASS, + [LOAD_CLASSDEREF] = LOAD_CLASSDEREF, + [LOAD_CLOSURE] = LOAD_CLOSURE, + [LOAD_CONST] = LOAD_CONST, + [LOAD_CONST__LOAD_FAST] = LOAD_CONST, + [LOAD_DEREF] = LOAD_DEREF, + [LOAD_FAST] = LOAD_FAST, + [LOAD_FAST__LOAD_CONST] = LOAD_FAST, + [LOAD_FAST__LOAD_FAST] = LOAD_FAST, + [LOAD_GLOBAL] = LOAD_GLOBAL, + [LOAD_GLOBAL_ADAPTIVE] = LOAD_GLOBAL, + [LOAD_GLOBAL_BUILTIN] = LOAD_GLOBAL, + [LOAD_GLOBAL_MODULE] = LOAD_GLOBAL, + [LOAD_METHOD] = LOAD_METHOD, + [LOAD_METHOD_ADAPTIVE] = LOAD_METHOD, + [LOAD_METHOD_CLASS] = LOAD_METHOD, + [LOAD_METHOD_MODULE] = LOAD_METHOD, + [LOAD_METHOD_NO_DICT] = LOAD_METHOD, + [LOAD_METHOD_WITH_DICT] = LOAD_METHOD, + [LOAD_METHOD_WITH_VALUES] = LOAD_METHOD, + [LOAD_NAME] = LOAD_NAME, + [MAKE_CELL] = MAKE_CELL, + [MAKE_FUNCTION] = MAKE_FUNCTION, + [MAP_ADD] = MAP_ADD, + [MATCH_CLASS] = MATCH_CLASS, + [MATCH_KEYS] = MATCH_KEYS, + [MATCH_MAPPING] = MATCH_MAPPING, + [MATCH_SEQUENCE] = MATCH_SEQUENCE, + [NOP] = NOP, + [POP_EXCEPT] = POP_EXCEPT, + [POP_JUMP_BACKWARD_IF_FALSE] = POP_JUMP_BACKWARD_IF_FALSE, + [POP_JUMP_BACKWARD_IF_NONE] = POP_JUMP_BACKWARD_IF_NONE, + [POP_JUMP_BACKWARD_IF_NOT_NONE] = POP_JUMP_BACKWARD_IF_NOT_NONE, + [POP_JUMP_BACKWARD_IF_TRUE] = POP_JUMP_BACKWARD_IF_TRUE, + [POP_JUMP_FORWARD_IF_FALSE] = POP_JUMP_FORWARD_IF_FALSE, + [POP_JUMP_FORWARD_IF_NONE] = POP_JUMP_FORWARD_IF_NONE, + [POP_JUMP_FORWARD_IF_NOT_NONE] = POP_JUMP_FORWARD_IF_NOT_NONE, + [POP_JUMP_FORWARD_IF_TRUE] = POP_JUMP_FORWARD_IF_TRUE, + [POP_TOP] = POP_TOP, + [PRECALL] = PRECALL, + [PRECALL_ADAPTIVE] = PRECALL, + [PRECALL_BOUND_METHOD] = PRECALL, + [PRECALL_BUILTIN_CLASS] = PRECALL, + [PRECALL_BUILTIN_FAST_WITH_KEYWORDS] = PRECALL, + [PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = PRECALL, + [PRECALL_NO_KW_BUILTIN_FAST] = PRECALL, + [PRECALL_NO_KW_BUILTIN_O] = PRECALL, + [PRECALL_NO_KW_ISINSTANCE] = PRECALL, + [PRECALL_NO_KW_LEN] = PRECALL, + [PRECALL_NO_KW_LIST_APPEND] = PRECALL, + [PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST] = PRECALL, + [PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = PRECALL, + [PRECALL_NO_KW_METHOD_DESCRIPTOR_O] = PRECALL, + [PRECALL_NO_KW_STR_1] = PRECALL, + [PRECALL_NO_KW_TUPLE_1] = PRECALL, + [PRECALL_NO_KW_TYPE_1] = PRECALL, + [PRECALL_PYFUNC] = PRECALL, + [PREP_RERAISE_STAR] = PREP_RERAISE_STAR, + [PRINT_EXPR] = PRINT_EXPR, + [PUSH_EXC_INFO] = PUSH_EXC_INFO, + [PUSH_NULL] = PUSH_NULL, + [RAISE_VARARGS] = RAISE_VARARGS, + [RERAISE] = RERAISE, + [RESUME] = RESUME, + [RESUME_QUICK] = RESUME, + [RETURN_GENERATOR] = RETURN_GENERATOR, + [RETURN_VALUE] = RETURN_VALUE, + [SEND] = SEND, + [SETUP_ANNOTATIONS] = SETUP_ANNOTATIONS, + [SET_ADD] = SET_ADD, + [SET_UPDATE] = SET_UPDATE, + [STORE_ATTR] = STORE_ATTR, + [STORE_ATTR_ADAPTIVE] = STORE_ATTR, + [STORE_ATTR_INSTANCE_VALUE] = STORE_ATTR, + [STORE_ATTR_SLOT] = STORE_ATTR, + [STORE_ATTR_WITH_HINT] = STORE_ATTR, + [STORE_DEREF] = STORE_DEREF, + [STORE_FAST] = STORE_FAST, + [STORE_FAST__LOAD_FAST] = STORE_FAST, + [STORE_FAST__STORE_FAST] = STORE_FAST, + [STORE_GLOBAL] = STORE_GLOBAL, + [STORE_NAME] = STORE_NAME, + [STORE_SUBSCR] = STORE_SUBSCR, + [STORE_SUBSCR_ADAPTIVE] = STORE_SUBSCR, + [STORE_SUBSCR_DICT] = STORE_SUBSCR, + [STORE_SUBSCR_LIST_INT] = STORE_SUBSCR, + [SWAP] = SWAP, + [UNARY_INVERT] = UNARY_INVERT, + [UNARY_NEGATIVE] = UNARY_NEGATIVE, + [UNARY_NOT] = UNARY_NOT, + [UNARY_POSITIVE] = UNARY_POSITIVE, + [UNPACK_EX] = UNPACK_EX, + [UNPACK_SEQUENCE] = UNPACK_SEQUENCE, + [UNPACK_SEQUENCE_ADAPTIVE] = UNPACK_SEQUENCE, + [UNPACK_SEQUENCE_LIST] = UNPACK_SEQUENCE, + [UNPACK_SEQUENCE_TUPLE] = UNPACK_SEQUENCE, + [UNPACK_SEQUENCE_TWO_TUPLE] = UNPACK_SEQUENCE, + [WITH_EXCEPT_START] = WITH_EXCEPT_START, + [YIELD_VALUE] = YIELD_VALUE, +}; +#endif // NEED_OPCODE_TABLES + +#ifdef Py_DEBUG +static const char *const _PyOpcode_OpName[256] = { + [CACHE] = "CACHE", + [POP_TOP] = "POP_TOP", + [PUSH_NULL] = "PUSH_NULL", + [BINARY_OP_ADAPTIVE] = "BINARY_OP_ADAPTIVE", + [BINARY_OP_ADD_FLOAT] = "BINARY_OP_ADD_FLOAT", + [BINARY_OP_ADD_INT] = "BINARY_OP_ADD_INT", + [BINARY_OP_ADD_UNICODE] = "BINARY_OP_ADD_UNICODE", + [BINARY_OP_INPLACE_ADD_UNICODE] = "BINARY_OP_INPLACE_ADD_UNICODE", + [BINARY_OP_MULTIPLY_FLOAT] = "BINARY_OP_MULTIPLY_FLOAT", + [NOP] = "NOP", + [UNARY_POSITIVE] = "UNARY_POSITIVE", + [UNARY_NEGATIVE] = "UNARY_NEGATIVE", + [UNARY_NOT] = "UNARY_NOT", + [BINARY_OP_MULTIPLY_INT] = "BINARY_OP_MULTIPLY_INT", + [BINARY_OP_SUBTRACT_FLOAT] = "BINARY_OP_SUBTRACT_FLOAT", + [UNARY_INVERT] = "UNARY_INVERT", + [BINARY_OP_SUBTRACT_INT] = "BINARY_OP_SUBTRACT_INT", + [BINARY_SUBSCR_ADAPTIVE] = "BINARY_SUBSCR_ADAPTIVE", + [BINARY_SUBSCR_DICT] = "BINARY_SUBSCR_DICT", + [BINARY_SUBSCR_GETITEM] = "BINARY_SUBSCR_GETITEM", + [BINARY_SUBSCR_LIST_INT] = "BINARY_SUBSCR_LIST_INT", + [BINARY_SUBSCR_TUPLE_INT] = "BINARY_SUBSCR_TUPLE_INT", + [CALL_ADAPTIVE] = "CALL_ADAPTIVE", + [CALL_PY_EXACT_ARGS] = "CALL_PY_EXACT_ARGS", + [CALL_PY_WITH_DEFAULTS] = "CALL_PY_WITH_DEFAULTS", + [BINARY_SUBSCR] = "BINARY_SUBSCR", + [COMPARE_OP_ADAPTIVE] = "COMPARE_OP_ADAPTIVE", + [COMPARE_OP_FLOAT_JUMP] = "COMPARE_OP_FLOAT_JUMP", + [COMPARE_OP_INT_JUMP] = "COMPARE_OP_INT_JUMP", + [COMPARE_OP_STR_JUMP] = "COMPARE_OP_STR_JUMP", + [GET_LEN] = "GET_LEN", + [MATCH_MAPPING] = "MATCH_MAPPING", + [MATCH_SEQUENCE] = "MATCH_SEQUENCE", + [MATCH_KEYS] = "MATCH_KEYS", + [EXTENDED_ARG_QUICK] = "EXTENDED_ARG_QUICK", + [PUSH_EXC_INFO] = "PUSH_EXC_INFO", + [CHECK_EXC_MATCH] = "CHECK_EXC_MATCH", + [CHECK_EG_MATCH] = "CHECK_EG_MATCH", + [JUMP_BACKWARD_QUICK] = "JUMP_BACKWARD_QUICK", + [LOAD_ATTR_ADAPTIVE] = "LOAD_ATTR_ADAPTIVE", + [LOAD_ATTR_INSTANCE_VALUE] = "LOAD_ATTR_INSTANCE_VALUE", + [LOAD_ATTR_MODULE] = "LOAD_ATTR_MODULE", + [LOAD_ATTR_SLOT] = "LOAD_ATTR_SLOT", + [LOAD_ATTR_WITH_HINT] = "LOAD_ATTR_WITH_HINT", + [LOAD_CONST__LOAD_FAST] = "LOAD_CONST__LOAD_FAST", + [LOAD_FAST__LOAD_CONST] = "LOAD_FAST__LOAD_CONST", + [LOAD_FAST__LOAD_FAST] = "LOAD_FAST__LOAD_FAST", + [LOAD_GLOBAL_ADAPTIVE] = "LOAD_GLOBAL_ADAPTIVE", + [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", + [WITH_EXCEPT_START] = "WITH_EXCEPT_START", + [GET_AITER] = "GET_AITER", + [GET_ANEXT] = "GET_ANEXT", + [BEFORE_ASYNC_WITH] = "BEFORE_ASYNC_WITH", + [BEFORE_WITH] = "BEFORE_WITH", + [END_ASYNC_FOR] = "END_ASYNC_FOR", + [LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE", + [LOAD_METHOD_ADAPTIVE] = "LOAD_METHOD_ADAPTIVE", + [LOAD_METHOD_CLASS] = "LOAD_METHOD_CLASS", + [LOAD_METHOD_MODULE] = "LOAD_METHOD_MODULE", + [LOAD_METHOD_NO_DICT] = "LOAD_METHOD_NO_DICT", + [STORE_SUBSCR] = "STORE_SUBSCR", + [DELETE_SUBSCR] = "DELETE_SUBSCR", + [LOAD_METHOD_WITH_DICT] = "LOAD_METHOD_WITH_DICT", + [LOAD_METHOD_WITH_VALUES] = "LOAD_METHOD_WITH_VALUES", + [PRECALL_ADAPTIVE] = "PRECALL_ADAPTIVE", + [PRECALL_BOUND_METHOD] = "PRECALL_BOUND_METHOD", + [PRECALL_BUILTIN_CLASS] = "PRECALL_BUILTIN_CLASS", + [PRECALL_BUILTIN_FAST_WITH_KEYWORDS] = "PRECALL_BUILTIN_FAST_WITH_KEYWORDS", + [GET_ITER] = "GET_ITER", + [GET_YIELD_FROM_ITER] = "GET_YIELD_FROM_ITER", + [PRINT_EXPR] = "PRINT_EXPR", + [LOAD_BUILD_CLASS] = "LOAD_BUILD_CLASS", + [PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", + [PRECALL_NO_KW_BUILTIN_FAST] = "PRECALL_NO_KW_BUILTIN_FAST", + [LOAD_ASSERTION_ERROR] = "LOAD_ASSERTION_ERROR", + [RETURN_GENERATOR] = "RETURN_GENERATOR", + [PRECALL_NO_KW_BUILTIN_O] = "PRECALL_NO_KW_BUILTIN_O", + [PRECALL_NO_KW_ISINSTANCE] = "PRECALL_NO_KW_ISINSTANCE", + [PRECALL_NO_KW_LEN] = "PRECALL_NO_KW_LEN", + [PRECALL_NO_KW_LIST_APPEND] = "PRECALL_NO_KW_LIST_APPEND", + [PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST] = "PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST", + [PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = "PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS", + [LIST_TO_TUPLE] = "LIST_TO_TUPLE", + [RETURN_VALUE] = "RETURN_VALUE", + [IMPORT_STAR] = "IMPORT_STAR", + [SETUP_ANNOTATIONS] = "SETUP_ANNOTATIONS", + [YIELD_VALUE] = "YIELD_VALUE", + [ASYNC_GEN_WRAP] = "ASYNC_GEN_WRAP", + [PREP_RERAISE_STAR] = "PREP_RERAISE_STAR", + [POP_EXCEPT] = "POP_EXCEPT", + [STORE_NAME] = "STORE_NAME", + [DELETE_NAME] = "DELETE_NAME", + [UNPACK_SEQUENCE] = "UNPACK_SEQUENCE", + [FOR_ITER] = "FOR_ITER", + [UNPACK_EX] = "UNPACK_EX", + [STORE_ATTR] = "STORE_ATTR", + [DELETE_ATTR] = "DELETE_ATTR", + [STORE_GLOBAL] = "STORE_GLOBAL", + [DELETE_GLOBAL] = "DELETE_GLOBAL", + [SWAP] = "SWAP", + [LOAD_CONST] = "LOAD_CONST", + [LOAD_NAME] = "LOAD_NAME", + [BUILD_TUPLE] = "BUILD_TUPLE", + [BUILD_LIST] = "BUILD_LIST", + [BUILD_SET] = "BUILD_SET", + [BUILD_MAP] = "BUILD_MAP", + [LOAD_ATTR] = "LOAD_ATTR", + [COMPARE_OP] = "COMPARE_OP", + [IMPORT_NAME] = "IMPORT_NAME", + [IMPORT_FROM] = "IMPORT_FROM", + [JUMP_FORWARD] = "JUMP_FORWARD", + [JUMP_IF_FALSE_OR_POP] = "JUMP_IF_FALSE_OR_POP", + [JUMP_IF_TRUE_OR_POP] = "JUMP_IF_TRUE_OR_POP", + [PRECALL_NO_KW_METHOD_DESCRIPTOR_O] = "PRECALL_NO_KW_METHOD_DESCRIPTOR_O", + [POP_JUMP_FORWARD_IF_FALSE] = "POP_JUMP_FORWARD_IF_FALSE", + [POP_JUMP_FORWARD_IF_TRUE] = "POP_JUMP_FORWARD_IF_TRUE", + [LOAD_GLOBAL] = "LOAD_GLOBAL", + [IS_OP] = "IS_OP", + [CONTAINS_OP] = "CONTAINS_OP", + [RERAISE] = "RERAISE", + [COPY] = "COPY", + [PRECALL_NO_KW_STR_1] = "PRECALL_NO_KW_STR_1", + [BINARY_OP] = "BINARY_OP", + [SEND] = "SEND", + [LOAD_FAST] = "LOAD_FAST", + [STORE_FAST] = "STORE_FAST", + [DELETE_FAST] = "DELETE_FAST", + [PRECALL_NO_KW_TUPLE_1] = "PRECALL_NO_KW_TUPLE_1", + [POP_JUMP_FORWARD_IF_NOT_NONE] = "POP_JUMP_FORWARD_IF_NOT_NONE", + [POP_JUMP_FORWARD_IF_NONE] = "POP_JUMP_FORWARD_IF_NONE", + [RAISE_VARARGS] = "RAISE_VARARGS", + [GET_AWAITABLE] = "GET_AWAITABLE", + [MAKE_FUNCTION] = "MAKE_FUNCTION", + [BUILD_SLICE] = "BUILD_SLICE", + [JUMP_BACKWARD_NO_INTERRUPT] = "JUMP_BACKWARD_NO_INTERRUPT", + [MAKE_CELL] = "MAKE_CELL", + [LOAD_CLOSURE] = "LOAD_CLOSURE", + [LOAD_DEREF] = "LOAD_DEREF", + [STORE_DEREF] = "STORE_DEREF", + [DELETE_DEREF] = "DELETE_DEREF", + [JUMP_BACKWARD] = "JUMP_BACKWARD", + [PRECALL_NO_KW_TYPE_1] = "PRECALL_NO_KW_TYPE_1", + [CALL_FUNCTION_EX] = "CALL_FUNCTION_EX", + [PRECALL_PYFUNC] = "PRECALL_PYFUNC", + [EXTENDED_ARG] = "EXTENDED_ARG", + [LIST_APPEND] = "LIST_APPEND", + [SET_ADD] = "SET_ADD", + [MAP_ADD] = "MAP_ADD", + [LOAD_CLASSDEREF] = "LOAD_CLASSDEREF", + [COPY_FREE_VARS] = "COPY_FREE_VARS", + [RESUME_QUICK] = "RESUME_QUICK", + [RESUME] = "RESUME", + [MATCH_CLASS] = "MATCH_CLASS", + [STORE_ATTR_ADAPTIVE] = "STORE_ATTR_ADAPTIVE", + [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", + [FORMAT_VALUE] = "FORMAT_VALUE", + [BUILD_CONST_KEY_MAP] = "BUILD_CONST_KEY_MAP", + [BUILD_STRING] = "BUILD_STRING", + [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", + [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT", + [LOAD_METHOD] = "LOAD_METHOD", + [STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST", + [LIST_EXTEND] = "LIST_EXTEND", + [SET_UPDATE] = "SET_UPDATE", + [DICT_MERGE] = "DICT_MERGE", + [DICT_UPDATE] = "DICT_UPDATE", + [PRECALL] = "PRECALL", + [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST", + [STORE_SUBSCR_ADAPTIVE] = "STORE_SUBSCR_ADAPTIVE", + [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT", + [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT", + [CALL] = "CALL", + [KW_NAMES] = "KW_NAMES", + [POP_JUMP_BACKWARD_IF_NOT_NONE] = "POP_JUMP_BACKWARD_IF_NOT_NONE", + [POP_JUMP_BACKWARD_IF_NONE] = "POP_JUMP_BACKWARD_IF_NONE", + [POP_JUMP_BACKWARD_IF_FALSE] = "POP_JUMP_BACKWARD_IF_FALSE", + [POP_JUMP_BACKWARD_IF_TRUE] = "POP_JUMP_BACKWARD_IF_TRUE", + [UNPACK_SEQUENCE_ADAPTIVE] = "UNPACK_SEQUENCE_ADAPTIVE", + [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST", + [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE", + [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE", + [181] = "<181>", + [182] = "<182>", + [183] = "<183>", + [184] = "<184>", + [185] = "<185>", + [186] = "<186>", + [187] = "<187>", + [188] = "<188>", + [189] = "<189>", + [190] = "<190>", + [191] = "<191>", + [192] = "<192>", + [193] = "<193>", + [194] = "<194>", + [195] = "<195>", + [196] = "<196>", + [197] = "<197>", + [198] = "<198>", + [199] = "<199>", + [200] = "<200>", + [201] = "<201>", + [202] = "<202>", + [203] = "<203>", + [204] = "<204>", + [205] = "<205>", + [206] = "<206>", + [207] = "<207>", + [208] = "<208>", + [209] = "<209>", + [210] = "<210>", + [211] = "<211>", + [212] = "<212>", + [213] = "<213>", + [214] = "<214>", + [215] = "<215>", + [216] = "<216>", + [217] = "<217>", + [218] = "<218>", + [219] = "<219>", + [220] = "<220>", + [221] = "<221>", + [222] = "<222>", + [223] = "<223>", + [224] = "<224>", + [225] = "<225>", + [226] = "<226>", + [227] = "<227>", + [228] = "<228>", + [229] = "<229>", + [230] = "<230>", + [231] = "<231>", + [232] = "<232>", + [233] = "<233>", + [234] = "<234>", + [235] = "<235>", + [236] = "<236>", + [237] = "<237>", + [238] = "<238>", + [239] = "<239>", + [240] = "<240>", + [241] = "<241>", + [242] = "<242>", + [243] = "<243>", + [244] = "<244>", + [245] = "<245>", + [246] = "<246>", + [247] = "<247>", + [248] = "<248>", + [249] = "<249>", + [250] = "<250>", + [251] = "<251>", + [252] = "<252>", + [253] = "<253>", + [254] = "<254>", + [DO_TRACING] = "DO_TRACING", +}; +#endif + +#define EXTRA_CASES \ + case 181: \ + case 182: \ + case 183: \ + case 184: \ + case 185: \ + case 186: \ + case 187: \ + case 188: \ + case 189: \ + case 190: \ + case 191: \ + case 192: \ + case 193: \ + case 194: \ + case 195: \ + case 196: \ + case 197: \ + case 198: \ + case 199: \ + case 200: \ + case 201: \ + case 202: \ + case 203: \ + case 204: \ + case 205: \ + case 206: \ + case 207: \ + case 208: \ + case 209: \ + case 210: \ + case 211: \ + case 212: \ + case 213: \ + case 214: \ + case 215: \ + case 216: \ + case 217: \ + case 218: \ + case 219: \ + case 220: \ + case 221: \ + case 222: \ + case 223: \ + case 224: \ + case 225: \ + case 226: \ + case 227: \ + case 228: \ + case 229: \ + case 230: \ + case 231: \ + case 232: \ + case 233: \ + case 234: \ + case 235: \ + case 236: \ + case 237: \ + case 238: \ + case 239: \ + case 240: \ + case 241: \ + case 242: \ + case 243: \ + case 244: \ + case 245: \ + case 246: \ + case 247: \ + case 248: \ + case 249: \ + case 250: \ + case 251: \ + case 252: \ + case 253: \ + case 254: \ + ; + +#ifdef __cplusplus +} +#endif +#endif // !Py_INTERNAL_OPCODE_H diff --git a/include/internal/pycore_pathconfig.h b/include/internal/pycore_pathconfig.h index 15447f54..b8deaa0c 100644 --- a/include/internal/pycore_pathconfig.h +++ b/include/internal/pycore_pathconfig.h @@ -8,64 +8,15 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -typedef struct _PyPathConfig { - /* Full path to the Python program */ - wchar_t *program_full_path; - wchar_t *prefix; - wchar_t *exec_prefix; - /* Set by Py_SetPath(), or computed by _PyConfig_InitPathConfig() */ - wchar_t *module_search_path; - /* Python program name */ - wchar_t *program_name; - /* Set by Py_SetPythonHome() or PYTHONHOME environment variable */ - wchar_t *home; -#ifdef MS_WINDOWS - /* isolated and site_import are used to set Py_IsolatedFlag and - Py_NoSiteFlag flags on Windows in read_pth_file(). These fields - are ignored when their value are equal to -1 (unset). */ - int isolated; - int site_import; - /* Set when a venv is detected */ - wchar_t *base_executable; -#endif -} _PyPathConfig; - -#ifdef MS_WINDOWS -# define _PyPathConfig_INIT \ - {.module_search_path = NULL, \ - .isolated = -1, \ - .site_import = -1} -#else -# define _PyPathConfig_INIT \ - {.module_search_path = NULL} -#endif -/* Note: _PyPathConfig_INIT sets other fields to 0/NULL */ - -PyAPI_DATA(_PyPathConfig) _Py_path_config; -#ifdef MS_WINDOWS -PyAPI_DATA(wchar_t*) _Py_dll_path; -#endif - -extern void _PyPathConfig_ClearGlobal(void); +PyAPI_FUNC(void) _PyPathConfig_ClearGlobal(void); +extern PyStatus _PyPathConfig_ReadGlobal(PyConfig *config); +extern PyStatus _PyPathConfig_UpdateGlobal(const PyConfig *config); +extern const wchar_t * _PyPathConfig_GetGlobalModuleSearchPath(void); -extern PyStatus _PyPathConfig_Calculate( - _PyPathConfig *pathconfig, - const PyConfig *config); extern int _PyPathConfig_ComputeSysPath0( const PyWideStringList *argv, PyObject **path0); -extern PyStatus _Py_FindEnvConfigValue( - FILE *env_file, - const wchar_t *key, - wchar_t **value_p); - -#ifdef MS_WINDOWS -extern wchar_t* _Py_GetDLLPath(void); -#endif -extern PyStatus _PyConfig_WritePathConfig(const PyConfig *config); -extern void _Py_DumpPathConfig(PyThreadState *tstate); -extern PyObject* _PyPathConfig_AsDict(void); #ifdef __cplusplus } diff --git a/include/internal/pycore_pyerrors.h b/include/internal/pycore_pyerrors.h index a5e97fe2..66f37942 100644 --- a/include/internal/pycore_pyerrors.h +++ b/include/internal/pycore_pyerrors.h @@ -8,6 +8,15 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif + +/* runtime lifecycle */ + +extern PyStatus _PyErr_InitTypes(PyInterpreterState *); +extern void _PyErr_FiniTypes(PyInterpreterState *); + + +/* other API */ + static inline PyObject* _PyErr_Occurred(PyThreadState *tstate) { assert(tstate != NULL); @@ -16,18 +25,11 @@ static inline PyObject* _PyErr_Occurred(PyThreadState *tstate) static inline void _PyErr_ClearExcState(_PyErr_StackItem *exc_state) { - PyObject *t, *v, *tb; - t = exc_state->exc_type; - v = exc_state->exc_value; - tb = exc_state->exc_traceback; - exc_state->exc_type = NULL; - exc_state->exc_value = NULL; - exc_state->exc_traceback = NULL; - Py_XDECREF(t); - Py_XDECREF(v); - Py_XDECREF(tb); + Py_CLEAR(exc_state->exc_value); } +PyAPI_FUNC(PyObject*) _PyErr_StackItemToExcInfoTuple( + _PyErr_StackItem *err_info); PyAPI_FUNC(void) _PyErr_Fetch( PyThreadState *tstate, @@ -82,6 +84,14 @@ PyAPI_FUNC(PyObject *) _PyErr_FormatFromCauseTstate( const char *format, ...); +PyAPI_FUNC(PyObject *) _PyExc_CreateExceptionGroup( + const char *msg, + PyObject *excs); + +PyAPI_FUNC(PyObject *) _PyExc_PrepReraiseStar( + PyObject *orig, + PyObject *excs); + PyAPI_FUNC(int) _PyErr_CheckSignalsTstate(PyThreadState *tstate); PyAPI_FUNC(void) _Py_DumpExtensionModules(int fd, PyInterpreterState *interp); diff --git a/include/internal/pycore_pylifecycle.h b/include/internal/pycore_pylifecycle.h index 524be9d4..b4718b8a 100644 --- a/include/internal/pycore_pylifecycle.h +++ b/include/internal/pycore_pylifecycle.h @@ -8,24 +8,8 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#ifdef HAVE_SIGNAL_H -#include -#endif - #include "pycore_runtime.h" // _PyRuntimeState -#ifndef NSIG -# if defined(_NSIG) -# define NSIG _NSIG /* For BSD/SysV */ -# elif defined(_SIGMAX) -# define NSIG (_SIGMAX + 1) /* For QNX */ -# elif defined(SIGMAX) -# define NSIG (SIGMAX + 1) /* For djgpp */ -# else -# define NSIG 64 /* Use a reasonable default value */ -# endif -#endif - /* Forward declarations */ struct _PyArgv; struct pyruntimestate; @@ -49,13 +33,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 int _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,49 +42,33 @@ 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 void _PySys_Fini(PyInterpreterState *interp); +extern int _PyBuiltins_AddExceptions(PyObject * bltinmod); 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); - +extern int _Py_Deepfreeze_Init(void); /* 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_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); extern void _PyWarnings_Fini(PyInterpreterState *interp); extern void _PyAST_Fini(PyInterpreterState *interp); extern void _PyAtExit_Fini(PyInterpreterState *interp); +extern void _PyThread_FiniType(PyInterpreterState *interp); +extern void _Py_Deepfreeze_Fini(void); +extern void _PyArg_Fini(void); extern PyStatus _PyGILState_Init(_PyRuntimeState *runtime); extern PyStatus _PyGILState_SetTstate(PyThreadState *tstate); @@ -122,6 +83,7 @@ PyAPI_FUNC(PyStatus) _Py_PreInitializeFromConfig( const PyConfig *config, const struct _PyArgv *args); +PyAPI_FUNC(wchar_t *) _Py_GetStdlibDir(void); PyAPI_FUNC(int) _Py_HandleSystemExit(int *exitcode_p); diff --git a/include/internal/pycore_pymath.h b/include/internal/pycore_pymath.h new file mode 100644 index 00000000..5c6aee2a --- /dev/null +++ b/include/internal/pycore_pymath.h @@ -0,0 +1,224 @@ +#ifndef Py_INTERNAL_PYMATH_H +#define Py_INTERNAL_PYMATH_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +/* _Py_ADJUST_ERANGE1(x) + * _Py_ADJUST_ERANGE2(x, y) + * Set errno to 0 before calling a libm function, and invoke one of these + * macros after, passing the function result(s) (_Py_ADJUST_ERANGE2 is useful + * for functions returning complex results). This makes two kinds of + * adjustments to errno: (A) If it looks like the platform libm set + * errno=ERANGE due to underflow, clear errno. (B) If it looks like the + * platform libm overflowed but didn't set errno, force errno to ERANGE. In + * effect, we're trying to force a useful implementation of C89 errno + * behavior. + * Caution: + * This isn't reliable. C99 no longer requires libm to set errno under + * any exceptional condition, but does require +- HUGE_VAL return + * values on overflow. A 754 box *probably* maps HUGE_VAL to a + * double infinity, and we're cool if that's so, unless the input + * was an infinity and an infinity is the expected result. A C89 + * system sets errno to ERANGE, so we check for that too. We're + * out of luck if a C99 754 box doesn't map HUGE_VAL to +Inf, or + * if the returned result is a NaN, or if a C89 box returns HUGE_VAL + * in non-overflow cases. + */ +static inline void _Py_ADJUST_ERANGE1(double x) +{ + if (errno == 0) { + if (x == Py_HUGE_VAL || x == -Py_HUGE_VAL) { + errno = ERANGE; + } + } + else if (errno == ERANGE && x == 0.0) { + errno = 0; + } +} + +static inline void _Py_ADJUST_ERANGE2(double x, double y) +{ + if (x == Py_HUGE_VAL || x == -Py_HUGE_VAL || + y == Py_HUGE_VAL || y == -Py_HUGE_VAL) + { + if (errno == 0) { + errno = ERANGE; + } + } + else if (errno == ERANGE) { + errno = 0; + } +} + +// Return whether integral type *type* is signed or not. +#define _Py_IntegralTypeSigned(type) \ + ((type)(-1) < 0) + +// Return the maximum value of integral type *type*. +#define _Py_IntegralTypeMax(type) \ + ((_Py_IntegralTypeSigned(type)) ? (((((type)1 << (sizeof(type)*CHAR_BIT - 2)) - 1) << 1) + 1) : ~(type)0) + +// Return the minimum value of integral type *type*. +#define _Py_IntegralTypeMin(type) \ + ((_Py_IntegralTypeSigned(type)) ? -_Py_IntegralTypeMax(type) - 1 : 0) + +// Check whether *v* is in the range of integral type *type*. This is most +// useful if *v* is floating-point, since demoting a floating-point *v* to an +// integral type that cannot represent *v*'s integral part is undefined +// behavior. +#define _Py_InIntegralTypeRange(type, v) \ + (_Py_IntegralTypeMin(type) <= v && v <= _Py_IntegralTypeMax(type)) + + +//--- HAVE_PY_SET_53BIT_PRECISION macro ------------------------------------ +// +// The functions _Py_dg_strtod() and _Py_dg_dtoa() in Python/dtoa.c (which are +// required to support the short float repr introduced in Python 3.1) require +// that the floating-point unit that's being used for arithmetic operations on +// C doubles is set to use 53-bit precision. It also requires that the FPU +// rounding mode is round-half-to-even, but that's less often an issue. +// +// If your FPU isn't already set to 53-bit precision/round-half-to-even, and +// you want to make use of _Py_dg_strtod() and _Py_dg_dtoa(), then you should: +// +// #define HAVE_PY_SET_53BIT_PRECISION 1 +// +// and also give appropriate definitions for the following three macros: +// +// * _Py_SET_53BIT_PRECISION_HEADER: any variable declarations needed to +// use the two macros below. +// * _Py_SET_53BIT_PRECISION_START: store original FPU settings, and +// set FPU to 53-bit precision/round-half-to-even +// * _Py_SET_53BIT_PRECISION_END: restore original FPU settings +// +// The macros are designed to be used within a single C function: see +// Python/pystrtod.c for an example of their use. + + +// Get and set x87 control word for gcc/x86 +#ifdef HAVE_GCC_ASM_FOR_X87 +#define HAVE_PY_SET_53BIT_PRECISION 1 + +// Functions defined in Python/pymath.c +extern unsigned short _Py_get_387controlword(void); +extern void _Py_set_387controlword(unsigned short); + +#define _Py_SET_53BIT_PRECISION_HEADER \ + unsigned short old_387controlword, new_387controlword +#define _Py_SET_53BIT_PRECISION_START \ + do { \ + old_387controlword = _Py_get_387controlword(); \ + new_387controlword = (old_387controlword & ~0x0f00) | 0x0200; \ + if (new_387controlword != old_387controlword) { \ + _Py_set_387controlword(new_387controlword); \ + } \ + } while (0) +#define _Py_SET_53BIT_PRECISION_END \ + do { \ + if (new_387controlword != old_387controlword) { \ + _Py_set_387controlword(old_387controlword); \ + } \ + } while (0) +#endif + +// Get and set x87 control word for VisualStudio/x86. +// x87 is not supported in 64-bit or ARM. +#if defined(_MSC_VER) && !defined(_WIN64) && !defined(_M_ARM) +#define HAVE_PY_SET_53BIT_PRECISION 1 + +#include // __control87_2() + +#define _Py_SET_53BIT_PRECISION_HEADER \ + unsigned int old_387controlword, new_387controlword, out_387controlword + // We use the __control87_2 function to set only the x87 control word. + // The SSE control word is unaffected. +#define _Py_SET_53BIT_PRECISION_START \ + do { \ + __control87_2(0, 0, &old_387controlword, NULL); \ + new_387controlword = \ + (old_387controlword & ~(_MCW_PC | _MCW_RC)) | (_PC_53 | _RC_NEAR); \ + if (new_387controlword != old_387controlword) { \ + __control87_2(new_387controlword, _MCW_PC | _MCW_RC, \ + &out_387controlword, NULL); \ + } \ + } while (0) +#define _Py_SET_53BIT_PRECISION_END \ + do { \ + if (new_387controlword != old_387controlword) { \ + __control87_2(old_387controlword, _MCW_PC | _MCW_RC, \ + &out_387controlword, NULL); \ + } \ + } while (0) +#endif + + +// MC68881 +#ifdef HAVE_GCC_ASM_FOR_MC68881 +#define HAVE_PY_SET_53BIT_PRECISION 1 +#define _Py_SET_53BIT_PRECISION_HEADER \ + unsigned int old_fpcr, new_fpcr +#define _Py_SET_53BIT_PRECISION_START \ + do { \ + __asm__ ("fmove.l %%fpcr,%0" : "=g" (old_fpcr)); \ + /* Set double precision / round to nearest. */ \ + new_fpcr = (old_fpcr & ~0xf0) | 0x80; \ + if (new_fpcr != old_fpcr) { \ + __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (new_fpcr));\ + } \ + } while (0) +#define _Py_SET_53BIT_PRECISION_END \ + do { \ + if (new_fpcr != old_fpcr) { \ + __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (old_fpcr)); \ + } \ + } while (0) +#endif + +// Default definitions are empty +#ifndef _Py_SET_53BIT_PRECISION_HEADER +# define _Py_SET_53BIT_PRECISION_HEADER +# define _Py_SET_53BIT_PRECISION_START +# define _Py_SET_53BIT_PRECISION_END +#endif + + +//--- _PY_SHORT_FLOAT_REPR macro ------------------------------------------- + +// If we can't guarantee 53-bit precision, don't use the code +// in Python/dtoa.c, but fall back to standard code. This +// means that repr of a float will be long (17 significant digits). +// +// Realistically, there are two things that could go wrong: +// +// (1) doubles aren't IEEE 754 doubles, or +// (2) we're on x86 with the rounding precision set to 64-bits +// (extended precision), and we don't know how to change +// the rounding precision. +#if !defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) && \ + !defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) && \ + !defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754) +# define _PY_SHORT_FLOAT_REPR 0 +#endif + +// Double rounding is symptomatic of use of extended precision on x86. +// If we're seeing double rounding, and we don't have any mechanism available +// for changing the FPU rounding precision, then don't use Python/dtoa.c. +#if defined(X87_DOUBLE_ROUNDING) && !defined(HAVE_PY_SET_53BIT_PRECISION) +# define _PY_SHORT_FLOAT_REPR 0 +#endif + +#ifndef _PY_SHORT_FLOAT_REPR +# define _PY_SHORT_FLOAT_REPR 1 +#endif + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_PYMATH_H */ diff --git a/include/internal/pycore_pymem.h b/include/internal/pycore_pymem.h index 49af1714..b9eea9d4 100644 --- a/include/internal/pycore_pymem.h +++ b/include/internal/pycore_pymem.h @@ -94,8 +94,21 @@ struct _PyTraceMalloc_Config { PyAPI_DATA(struct _PyTraceMalloc_Config) _Py_tracemalloc_config; +/* Allocate memory directly from the O/S virtual memory system, + * where supported. Otherwise fallback on malloc */ +void *_PyObject_VirtualAlloc(size_t size); +void _PyObject_VirtualFree(void *, size_t size); + +/* This function returns the number of allocated memory blocks, regardless of size */ +PyAPI_FUNC(Py_ssize_t) _Py_GetAllocatedBlocks(void); + +/* Macros */ +#ifdef WITH_PYMALLOC +// Export the symbol for the 3rd party guppy3 project +PyAPI_FUNC(int) _PyObject_DebugMallocStats(FILE *out); +#endif #ifdef __cplusplus } #endif -#endif /* !Py_INTERNAL_PYMEM_H */ +#endif // !Py_INTERNAL_PYMEM_H diff --git a/include/internal/pycore_pystate.h b/include/internal/pycore_pystate.h index 4b894f3e..cb8f1157 100644 --- a/include/internal/pycore_pystate.h +++ b/include/internal/pycore_pystate.h @@ -21,12 +21,27 @@ _Py_IsMainThread(void) } +static inline PyInterpreterState * +_PyInterpreterState_Main(void) +{ + return _PyRuntime.interpreters.main; +} + static inline int _Py_IsMainInterpreter(PyInterpreterState *interp) { - /* Use directly _PyRuntime rather than tstate->interp->runtime, since - this function is used in performance critical code path (ceval) */ - return (interp == _PyRuntime.interpreters.main); + return (interp == _PyInterpreterState_Main()); +} + + +static inline const PyConfig * +_Py_GetMainConfig(void) +{ + PyInterpreterState *interp = _PyInterpreterState_Main(); + if (interp == NULL) { + return NULL; + } + return _PyInterpreterState_GetConfig(interp); } @@ -34,7 +49,7 @@ _Py_IsMainInterpreter(PyInterpreterState *interp) static inline int _Py_ThreadCanHandleSignals(PyInterpreterState *interp) { - return (_Py_IsMainThread() && interp == _PyRuntime.interpreters.main); + return (_Py_IsMainThread() && _Py_IsMainInterpreter(interp)); } @@ -49,18 +64,10 @@ _Py_ThreadCanHandlePendingCalls(void) /* Variable and macro for in-line access to current thread and interpreter state */ -#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS -PyAPI_FUNC(PyThreadState*) _PyThreadState_GetTSS(void); -#endif - static inline PyThreadState* _PyRuntimeState_GetThreadState(_PyRuntimeState *runtime) { -#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS - return _PyThreadState_GetTSS(); -#else return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->gilstate.tstate_current); -#endif } /* Get the current Python thread state. @@ -71,21 +78,13 @@ _PyRuntimeState_GetThreadState(_PyRuntimeState *runtime) The caller must hold the GIL. - See also PyThreadState_Get() and PyThreadState_GET(). */ + See also PyThreadState_Get() and _PyThreadState_UncheckedGet(). */ static inline PyThreadState* _PyThreadState_GET(void) { -#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS - return _PyThreadState_GetTSS(); -#else return _PyRuntimeState_GetThreadState(&_PyRuntime); -#endif } -/* Redefine PyThreadState_GET() as an alias to _PyThreadState_GET() */ -#undef PyThreadState_GET -#define PyThreadState_GET() _PyThreadState_GET() - PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalError_TstateNULL(const char *func); static inline void @@ -118,14 +117,29 @@ static inline PyInterpreterState* _PyInterpreterState_GET(void) { } -/* Other */ +// PyThreadState functions +PyAPI_FUNC(void) _PyThreadState_SetCurrent(PyThreadState *tstate); +// We keep this around exclusively for stable ABI compatibility. PyAPI_FUNC(void) _PyThreadState_Init( PyThreadState *tstate); PyAPI_FUNC(void) _PyThreadState_DeleteExcept( _PyRuntimeState *runtime, PyThreadState *tstate); + +static inline void +_PyThreadState_UpdateTracingState(PyThreadState *tstate) +{ + bool use_tracing = + (tstate->tracing == 0) && + (tstate->c_tracefunc != NULL || tstate->c_profilefunc != NULL); + tstate->cframe->use_tracing = (use_tracing ? 255 : 0); +} + + +/* Other */ + PyAPI_FUNC(PyThreadState *) _PyThreadState_Swap( struct _gilstate_runtime_state *gilstate, PyThreadState *newts); @@ -142,7 +156,7 @@ extern void _PySignal_AfterFork(void); PyAPI_FUNC(int) _PyState_AddModule( PyThreadState *tstate, PyObject* module, - struct PyModuleDef* def); + PyModuleDef* def); PyAPI_FUNC(int) _PyOS_InterruptOccurred(PyThreadState *tstate); diff --git a/include/internal/pycore_runtime.h b/include/internal/pycore_runtime.h index bcd710c4..ae63ae74 100644 --- a/include/internal/pycore_runtime.h +++ b/include/internal/pycore_runtime.h @@ -8,8 +8,12 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_atomic.h" /* _Py_atomic_address */ -#include "pycore_gil.h" // struct _gil_runtime_state +#include "pycore_atomic.h" /* _Py_atomic_address */ +#include "pycore_gil.h" // struct _gil_runtime_state +#include "pycore_global_objects.h" // struct _Py_global_objects +#include "pycore_interp.h" // PyInterpreterState +#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids + /* ceval state */ @@ -19,9 +23,7 @@ struct _ceval_runtime_state { the main thread of the main interpreter can handle signals: see _Py_ThreadCanHandleSignals(). */ _Py_atomic_int signals_pending; -#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS struct _gil_runtime_state gil; -#endif }; /* GIL state */ @@ -49,16 +51,18 @@ 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 */ +/* _PyRuntimeState holds the global state for the CPython runtime. + That data is exposed in the internal API as a static variable (_PyRuntime). + */ typedef struct pyruntimestate { + /* Has been initialized to a safe state. + + In order to be effective, this must be set to 0 during or right + after allocation. */ + int _initialized; + /* Is running Py_PreInitialize()? */ int preinitializing; @@ -80,7 +84,11 @@ typedef struct pyruntimestate { struct pyinterpreters { PyThread_type_lock mutex; + /* The linked list of interpreters, newest first. */ PyInterpreterState *head; + /* The runtime's initial interpreter, which has a special role + in the operation of the runtime. It is also often the only + interpreter. */ PyInterpreterState *main; /* _next_interp_id is an auto-numbered sequence of small integers. It gets initialized in _PyInterpreterState_Init(), @@ -117,13 +125,29 @@ typedef struct pyruntimestate { struct _Py_unicode_runtime_ids unicode_ids; - // XXX Consolidate globals found via the check-c-globals script. + /* All the objects that are shared by the runtime's interpreters. */ + struct _Py_global_objects global_objects; + + /* The following fields are here to avoid allocation during init. + The data is exposed through _PyRuntimeState pointer fields. + These fields should not be accessed directly outside of init. + + All other _PyRuntimeState pointer fields are populated when + needed and default to NULL. + + For now there are some exceptions to that rule, which require + allocation during init. These will be addressed on a case-by-case + basis. Most notably, we don't pre-allocated the several mutex + (PyThread_type_lock) fields, because on Windows we only ever get + a pointer type. + */ + + /* PyInterpreterState.interpreters.main */ + PyInterpreterState _main_interpreter; } _PyRuntimeState; -#define _PyRuntimeState_INIT \ - {.preinitialized = 0, .core_initialized = 0, .initialized = 0} -/* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */ +/* other API */ PyAPI_DATA(_PyRuntimeState) _PyRuntime; diff --git a/include/internal/pycore_runtime_init.h b/include/internal/pycore_runtime_init.h new file mode 100644 index 00000000..13eae1e4 --- /dev/null +++ b/include/internal/pycore_runtime_init.h @@ -0,0 +1,1256 @@ +#ifndef Py_INTERNAL_RUNTIME_INIT_H +#define Py_INTERNAL_RUNTIME_INIT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include "pycore_object.h" + + +/* The static initializers defined here should only be used + in the runtime init code (in pystate.c and pylifecycle.c). */ + + +#define _PyRuntimeState_INIT \ + { \ + .gilstate = { \ + .check_enabled = 1, \ + /* A TSS key must be initialized with Py_tss_NEEDS_INIT \ + in accordance with the specification. */ \ + .autoTSSkey = Py_tss_NEEDS_INIT, \ + }, \ + .interpreters = { \ + /* This prevents interpreters from getting created \ + until _PyInterpreterState_Enable() is called. */ \ + .next_id = -1, \ + }, \ + .global_objects = _Py_global_objects_INIT, \ + ._main_interpreter = _PyInterpreterState_INIT, \ + } + +#ifdef HAVE_DLOPEN +# include +# if HAVE_DECL_RTLD_NOW +# define _Py_DLOPEN_FLAGS RTLD_NOW +# else +# define _Py_DLOPEN_FLAGS RTLD_LAZY +# endif +# define DLOPENFLAGS_INIT .dlopenflags = _Py_DLOPEN_FLAGS, +#else +# define _Py_DLOPEN_FLAGS 0 +# define DLOPENFLAGS_INIT +#endif + +#define _PyInterpreterState_INIT \ + { \ + ._static = 1, \ + .id_refcount = -1, \ + DLOPENFLAGS_INIT \ + .ceval = { \ + .recursion_limit = Py_DEFAULT_RECURSION_LIMIT, \ + }, \ + .gc = { \ + .enabled = 1, \ + .generations = { \ + /* .head is set in _PyGC_InitState(). */ \ + { .threshold = 700, }, \ + { .threshold = 10, }, \ + { .threshold = 10, }, \ + }, \ + }, \ + ._initial_thread = _PyThreadState_INIT, \ + } + +#define _PyThreadState_INIT \ + { \ + ._static = 1, \ + .recursion_limit = Py_DEFAULT_RECURSION_LIMIT, \ + .context_ver = 1, \ + } + + +// global objects + +#define _PyLong_DIGIT_INIT(val) \ + { \ + _PyVarObject_IMMORTAL_INIT(&PyLong_Type, \ + ((val) == 0 ? 0 : ((val) > 0 ? 1 : -1))), \ + .ob_digit = { ((val) >= 0 ? (val) : -(val)) }, \ + } + +#define _PyBytes_SIMPLE_INIT(CH, LEN) \ + { \ + _PyVarObject_IMMORTAL_INIT(&PyBytes_Type, LEN), \ + .ob_shash = -1, \ + .ob_sval = { CH }, \ + } +#define _PyBytes_CHAR_INIT(CH) \ + { \ + _PyBytes_SIMPLE_INIT(CH, 1) \ + } + +#define _PyUnicode_ASCII_BASE_INIT(LITERAL, ASCII) \ + { \ + .ob_base = _PyObject_IMMORTAL_INIT(&PyUnicode_Type), \ + .length = sizeof(LITERAL) - 1, \ + .hash = -1, \ + .state = { \ + .kind = 1, \ + .compact = 1, \ + .ascii = ASCII, \ + .ready = 1, \ + }, \ + } +#define _PyASCIIObject_INIT(LITERAL) \ + { \ + ._ascii = _PyUnicode_ASCII_BASE_INIT(LITERAL, 1), \ + ._data = LITERAL \ + } +#define INIT_STR(NAME, LITERAL) \ + ._ ## NAME = _PyASCIIObject_INIT(LITERAL) +#define INIT_ID(NAME) \ + ._ ## NAME = _PyASCIIObject_INIT(#NAME) +#define _PyUnicode_LATIN1_INIT(LITERAL) \ + { \ + ._latin1 = { \ + ._base = _PyUnicode_ASCII_BASE_INIT(LITERAL, 0), \ + }, \ + ._data = LITERAL, \ + } + +/* The following is auto-generated by Tools/scripts/generate_global_objects.py. */ +#define _Py_global_objects_INIT { \ + .singletons = { \ + .small_ints = { \ + _PyLong_DIGIT_INIT(-5), \ + _PyLong_DIGIT_INIT(-4), \ + _PyLong_DIGIT_INIT(-3), \ + _PyLong_DIGIT_INIT(-2), \ + _PyLong_DIGIT_INIT(-1), \ + _PyLong_DIGIT_INIT(0), \ + _PyLong_DIGIT_INIT(1), \ + _PyLong_DIGIT_INIT(2), \ + _PyLong_DIGIT_INIT(3), \ + _PyLong_DIGIT_INIT(4), \ + _PyLong_DIGIT_INIT(5), \ + _PyLong_DIGIT_INIT(6), \ + _PyLong_DIGIT_INIT(7), \ + _PyLong_DIGIT_INIT(8), \ + _PyLong_DIGIT_INIT(9), \ + _PyLong_DIGIT_INIT(10), \ + _PyLong_DIGIT_INIT(11), \ + _PyLong_DIGIT_INIT(12), \ + _PyLong_DIGIT_INIT(13), \ + _PyLong_DIGIT_INIT(14), \ + _PyLong_DIGIT_INIT(15), \ + _PyLong_DIGIT_INIT(16), \ + _PyLong_DIGIT_INIT(17), \ + _PyLong_DIGIT_INIT(18), \ + _PyLong_DIGIT_INIT(19), \ + _PyLong_DIGIT_INIT(20), \ + _PyLong_DIGIT_INIT(21), \ + _PyLong_DIGIT_INIT(22), \ + _PyLong_DIGIT_INIT(23), \ + _PyLong_DIGIT_INIT(24), \ + _PyLong_DIGIT_INIT(25), \ + _PyLong_DIGIT_INIT(26), \ + _PyLong_DIGIT_INIT(27), \ + _PyLong_DIGIT_INIT(28), \ + _PyLong_DIGIT_INIT(29), \ + _PyLong_DIGIT_INIT(30), \ + _PyLong_DIGIT_INIT(31), \ + _PyLong_DIGIT_INIT(32), \ + _PyLong_DIGIT_INIT(33), \ + _PyLong_DIGIT_INIT(34), \ + _PyLong_DIGIT_INIT(35), \ + _PyLong_DIGIT_INIT(36), \ + _PyLong_DIGIT_INIT(37), \ + _PyLong_DIGIT_INIT(38), \ + _PyLong_DIGIT_INIT(39), \ + _PyLong_DIGIT_INIT(40), \ + _PyLong_DIGIT_INIT(41), \ + _PyLong_DIGIT_INIT(42), \ + _PyLong_DIGIT_INIT(43), \ + _PyLong_DIGIT_INIT(44), \ + _PyLong_DIGIT_INIT(45), \ + _PyLong_DIGIT_INIT(46), \ + _PyLong_DIGIT_INIT(47), \ + _PyLong_DIGIT_INIT(48), \ + _PyLong_DIGIT_INIT(49), \ + _PyLong_DIGIT_INIT(50), \ + _PyLong_DIGIT_INIT(51), \ + _PyLong_DIGIT_INIT(52), \ + _PyLong_DIGIT_INIT(53), \ + _PyLong_DIGIT_INIT(54), \ + _PyLong_DIGIT_INIT(55), \ + _PyLong_DIGIT_INIT(56), \ + _PyLong_DIGIT_INIT(57), \ + _PyLong_DIGIT_INIT(58), \ + _PyLong_DIGIT_INIT(59), \ + _PyLong_DIGIT_INIT(60), \ + _PyLong_DIGIT_INIT(61), \ + _PyLong_DIGIT_INIT(62), \ + _PyLong_DIGIT_INIT(63), \ + _PyLong_DIGIT_INIT(64), \ + _PyLong_DIGIT_INIT(65), \ + _PyLong_DIGIT_INIT(66), \ + _PyLong_DIGIT_INIT(67), \ + _PyLong_DIGIT_INIT(68), \ + _PyLong_DIGIT_INIT(69), \ + _PyLong_DIGIT_INIT(70), \ + _PyLong_DIGIT_INIT(71), \ + _PyLong_DIGIT_INIT(72), \ + _PyLong_DIGIT_INIT(73), \ + _PyLong_DIGIT_INIT(74), \ + _PyLong_DIGIT_INIT(75), \ + _PyLong_DIGIT_INIT(76), \ + _PyLong_DIGIT_INIT(77), \ + _PyLong_DIGIT_INIT(78), \ + _PyLong_DIGIT_INIT(79), \ + _PyLong_DIGIT_INIT(80), \ + _PyLong_DIGIT_INIT(81), \ + _PyLong_DIGIT_INIT(82), \ + _PyLong_DIGIT_INIT(83), \ + _PyLong_DIGIT_INIT(84), \ + _PyLong_DIGIT_INIT(85), \ + _PyLong_DIGIT_INIT(86), \ + _PyLong_DIGIT_INIT(87), \ + _PyLong_DIGIT_INIT(88), \ + _PyLong_DIGIT_INIT(89), \ + _PyLong_DIGIT_INIT(90), \ + _PyLong_DIGIT_INIT(91), \ + _PyLong_DIGIT_INIT(92), \ + _PyLong_DIGIT_INIT(93), \ + _PyLong_DIGIT_INIT(94), \ + _PyLong_DIGIT_INIT(95), \ + _PyLong_DIGIT_INIT(96), \ + _PyLong_DIGIT_INIT(97), \ + _PyLong_DIGIT_INIT(98), \ + _PyLong_DIGIT_INIT(99), \ + _PyLong_DIGIT_INIT(100), \ + _PyLong_DIGIT_INIT(101), \ + _PyLong_DIGIT_INIT(102), \ + _PyLong_DIGIT_INIT(103), \ + _PyLong_DIGIT_INIT(104), \ + _PyLong_DIGIT_INIT(105), \ + _PyLong_DIGIT_INIT(106), \ + _PyLong_DIGIT_INIT(107), \ + _PyLong_DIGIT_INIT(108), \ + _PyLong_DIGIT_INIT(109), \ + _PyLong_DIGIT_INIT(110), \ + _PyLong_DIGIT_INIT(111), \ + _PyLong_DIGIT_INIT(112), \ + _PyLong_DIGIT_INIT(113), \ + _PyLong_DIGIT_INIT(114), \ + _PyLong_DIGIT_INIT(115), \ + _PyLong_DIGIT_INIT(116), \ + _PyLong_DIGIT_INIT(117), \ + _PyLong_DIGIT_INIT(118), \ + _PyLong_DIGIT_INIT(119), \ + _PyLong_DIGIT_INIT(120), \ + _PyLong_DIGIT_INIT(121), \ + _PyLong_DIGIT_INIT(122), \ + _PyLong_DIGIT_INIT(123), \ + _PyLong_DIGIT_INIT(124), \ + _PyLong_DIGIT_INIT(125), \ + _PyLong_DIGIT_INIT(126), \ + _PyLong_DIGIT_INIT(127), \ + _PyLong_DIGIT_INIT(128), \ + _PyLong_DIGIT_INIT(129), \ + _PyLong_DIGIT_INIT(130), \ + _PyLong_DIGIT_INIT(131), \ + _PyLong_DIGIT_INIT(132), \ + _PyLong_DIGIT_INIT(133), \ + _PyLong_DIGIT_INIT(134), \ + _PyLong_DIGIT_INIT(135), \ + _PyLong_DIGIT_INIT(136), \ + _PyLong_DIGIT_INIT(137), \ + _PyLong_DIGIT_INIT(138), \ + _PyLong_DIGIT_INIT(139), \ + _PyLong_DIGIT_INIT(140), \ + _PyLong_DIGIT_INIT(141), \ + _PyLong_DIGIT_INIT(142), \ + _PyLong_DIGIT_INIT(143), \ + _PyLong_DIGIT_INIT(144), \ + _PyLong_DIGIT_INIT(145), \ + _PyLong_DIGIT_INIT(146), \ + _PyLong_DIGIT_INIT(147), \ + _PyLong_DIGIT_INIT(148), \ + _PyLong_DIGIT_INIT(149), \ + _PyLong_DIGIT_INIT(150), \ + _PyLong_DIGIT_INIT(151), \ + _PyLong_DIGIT_INIT(152), \ + _PyLong_DIGIT_INIT(153), \ + _PyLong_DIGIT_INIT(154), \ + _PyLong_DIGIT_INIT(155), \ + _PyLong_DIGIT_INIT(156), \ + _PyLong_DIGIT_INIT(157), \ + _PyLong_DIGIT_INIT(158), \ + _PyLong_DIGIT_INIT(159), \ + _PyLong_DIGIT_INIT(160), \ + _PyLong_DIGIT_INIT(161), \ + _PyLong_DIGIT_INIT(162), \ + _PyLong_DIGIT_INIT(163), \ + _PyLong_DIGIT_INIT(164), \ + _PyLong_DIGIT_INIT(165), \ + _PyLong_DIGIT_INIT(166), \ + _PyLong_DIGIT_INIT(167), \ + _PyLong_DIGIT_INIT(168), \ + _PyLong_DIGIT_INIT(169), \ + _PyLong_DIGIT_INIT(170), \ + _PyLong_DIGIT_INIT(171), \ + _PyLong_DIGIT_INIT(172), \ + _PyLong_DIGIT_INIT(173), \ + _PyLong_DIGIT_INIT(174), \ + _PyLong_DIGIT_INIT(175), \ + _PyLong_DIGIT_INIT(176), \ + _PyLong_DIGIT_INIT(177), \ + _PyLong_DIGIT_INIT(178), \ + _PyLong_DIGIT_INIT(179), \ + _PyLong_DIGIT_INIT(180), \ + _PyLong_DIGIT_INIT(181), \ + _PyLong_DIGIT_INIT(182), \ + _PyLong_DIGIT_INIT(183), \ + _PyLong_DIGIT_INIT(184), \ + _PyLong_DIGIT_INIT(185), \ + _PyLong_DIGIT_INIT(186), \ + _PyLong_DIGIT_INIT(187), \ + _PyLong_DIGIT_INIT(188), \ + _PyLong_DIGIT_INIT(189), \ + _PyLong_DIGIT_INIT(190), \ + _PyLong_DIGIT_INIT(191), \ + _PyLong_DIGIT_INIT(192), \ + _PyLong_DIGIT_INIT(193), \ + _PyLong_DIGIT_INIT(194), \ + _PyLong_DIGIT_INIT(195), \ + _PyLong_DIGIT_INIT(196), \ + _PyLong_DIGIT_INIT(197), \ + _PyLong_DIGIT_INIT(198), \ + _PyLong_DIGIT_INIT(199), \ + _PyLong_DIGIT_INIT(200), \ + _PyLong_DIGIT_INIT(201), \ + _PyLong_DIGIT_INIT(202), \ + _PyLong_DIGIT_INIT(203), \ + _PyLong_DIGIT_INIT(204), \ + _PyLong_DIGIT_INIT(205), \ + _PyLong_DIGIT_INIT(206), \ + _PyLong_DIGIT_INIT(207), \ + _PyLong_DIGIT_INIT(208), \ + _PyLong_DIGIT_INIT(209), \ + _PyLong_DIGIT_INIT(210), \ + _PyLong_DIGIT_INIT(211), \ + _PyLong_DIGIT_INIT(212), \ + _PyLong_DIGIT_INIT(213), \ + _PyLong_DIGIT_INIT(214), \ + _PyLong_DIGIT_INIT(215), \ + _PyLong_DIGIT_INIT(216), \ + _PyLong_DIGIT_INIT(217), \ + _PyLong_DIGIT_INIT(218), \ + _PyLong_DIGIT_INIT(219), \ + _PyLong_DIGIT_INIT(220), \ + _PyLong_DIGIT_INIT(221), \ + _PyLong_DIGIT_INIT(222), \ + _PyLong_DIGIT_INIT(223), \ + _PyLong_DIGIT_INIT(224), \ + _PyLong_DIGIT_INIT(225), \ + _PyLong_DIGIT_INIT(226), \ + _PyLong_DIGIT_INIT(227), \ + _PyLong_DIGIT_INIT(228), \ + _PyLong_DIGIT_INIT(229), \ + _PyLong_DIGIT_INIT(230), \ + _PyLong_DIGIT_INIT(231), \ + _PyLong_DIGIT_INIT(232), \ + _PyLong_DIGIT_INIT(233), \ + _PyLong_DIGIT_INIT(234), \ + _PyLong_DIGIT_INIT(235), \ + _PyLong_DIGIT_INIT(236), \ + _PyLong_DIGIT_INIT(237), \ + _PyLong_DIGIT_INIT(238), \ + _PyLong_DIGIT_INIT(239), \ + _PyLong_DIGIT_INIT(240), \ + _PyLong_DIGIT_INIT(241), \ + _PyLong_DIGIT_INIT(242), \ + _PyLong_DIGIT_INIT(243), \ + _PyLong_DIGIT_INIT(244), \ + _PyLong_DIGIT_INIT(245), \ + _PyLong_DIGIT_INIT(246), \ + _PyLong_DIGIT_INIT(247), \ + _PyLong_DIGIT_INIT(248), \ + _PyLong_DIGIT_INIT(249), \ + _PyLong_DIGIT_INIT(250), \ + _PyLong_DIGIT_INIT(251), \ + _PyLong_DIGIT_INIT(252), \ + _PyLong_DIGIT_INIT(253), \ + _PyLong_DIGIT_INIT(254), \ + _PyLong_DIGIT_INIT(255), \ + _PyLong_DIGIT_INIT(256), \ + }, \ + \ + .bytes_empty = _PyBytes_SIMPLE_INIT(0, 0), \ + .bytes_characters = { \ + _PyBytes_CHAR_INIT(0), \ + _PyBytes_CHAR_INIT(1), \ + _PyBytes_CHAR_INIT(2), \ + _PyBytes_CHAR_INIT(3), \ + _PyBytes_CHAR_INIT(4), \ + _PyBytes_CHAR_INIT(5), \ + _PyBytes_CHAR_INIT(6), \ + _PyBytes_CHAR_INIT(7), \ + _PyBytes_CHAR_INIT(8), \ + _PyBytes_CHAR_INIT(9), \ + _PyBytes_CHAR_INIT(10), \ + _PyBytes_CHAR_INIT(11), \ + _PyBytes_CHAR_INIT(12), \ + _PyBytes_CHAR_INIT(13), \ + _PyBytes_CHAR_INIT(14), \ + _PyBytes_CHAR_INIT(15), \ + _PyBytes_CHAR_INIT(16), \ + _PyBytes_CHAR_INIT(17), \ + _PyBytes_CHAR_INIT(18), \ + _PyBytes_CHAR_INIT(19), \ + _PyBytes_CHAR_INIT(20), \ + _PyBytes_CHAR_INIT(21), \ + _PyBytes_CHAR_INIT(22), \ + _PyBytes_CHAR_INIT(23), \ + _PyBytes_CHAR_INIT(24), \ + _PyBytes_CHAR_INIT(25), \ + _PyBytes_CHAR_INIT(26), \ + _PyBytes_CHAR_INIT(27), \ + _PyBytes_CHAR_INIT(28), \ + _PyBytes_CHAR_INIT(29), \ + _PyBytes_CHAR_INIT(30), \ + _PyBytes_CHAR_INIT(31), \ + _PyBytes_CHAR_INIT(32), \ + _PyBytes_CHAR_INIT(33), \ + _PyBytes_CHAR_INIT(34), \ + _PyBytes_CHAR_INIT(35), \ + _PyBytes_CHAR_INIT(36), \ + _PyBytes_CHAR_INIT(37), \ + _PyBytes_CHAR_INIT(38), \ + _PyBytes_CHAR_INIT(39), \ + _PyBytes_CHAR_INIT(40), \ + _PyBytes_CHAR_INIT(41), \ + _PyBytes_CHAR_INIT(42), \ + _PyBytes_CHAR_INIT(43), \ + _PyBytes_CHAR_INIT(44), \ + _PyBytes_CHAR_INIT(45), \ + _PyBytes_CHAR_INIT(46), \ + _PyBytes_CHAR_INIT(47), \ + _PyBytes_CHAR_INIT(48), \ + _PyBytes_CHAR_INIT(49), \ + _PyBytes_CHAR_INIT(50), \ + _PyBytes_CHAR_INIT(51), \ + _PyBytes_CHAR_INIT(52), \ + _PyBytes_CHAR_INIT(53), \ + _PyBytes_CHAR_INIT(54), \ + _PyBytes_CHAR_INIT(55), \ + _PyBytes_CHAR_INIT(56), \ + _PyBytes_CHAR_INIT(57), \ + _PyBytes_CHAR_INIT(58), \ + _PyBytes_CHAR_INIT(59), \ + _PyBytes_CHAR_INIT(60), \ + _PyBytes_CHAR_INIT(61), \ + _PyBytes_CHAR_INIT(62), \ + _PyBytes_CHAR_INIT(63), \ + _PyBytes_CHAR_INIT(64), \ + _PyBytes_CHAR_INIT(65), \ + _PyBytes_CHAR_INIT(66), \ + _PyBytes_CHAR_INIT(67), \ + _PyBytes_CHAR_INIT(68), \ + _PyBytes_CHAR_INIT(69), \ + _PyBytes_CHAR_INIT(70), \ + _PyBytes_CHAR_INIT(71), \ + _PyBytes_CHAR_INIT(72), \ + _PyBytes_CHAR_INIT(73), \ + _PyBytes_CHAR_INIT(74), \ + _PyBytes_CHAR_INIT(75), \ + _PyBytes_CHAR_INIT(76), \ + _PyBytes_CHAR_INIT(77), \ + _PyBytes_CHAR_INIT(78), \ + _PyBytes_CHAR_INIT(79), \ + _PyBytes_CHAR_INIT(80), \ + _PyBytes_CHAR_INIT(81), \ + _PyBytes_CHAR_INIT(82), \ + _PyBytes_CHAR_INIT(83), \ + _PyBytes_CHAR_INIT(84), \ + _PyBytes_CHAR_INIT(85), \ + _PyBytes_CHAR_INIT(86), \ + _PyBytes_CHAR_INIT(87), \ + _PyBytes_CHAR_INIT(88), \ + _PyBytes_CHAR_INIT(89), \ + _PyBytes_CHAR_INIT(90), \ + _PyBytes_CHAR_INIT(91), \ + _PyBytes_CHAR_INIT(92), \ + _PyBytes_CHAR_INIT(93), \ + _PyBytes_CHAR_INIT(94), \ + _PyBytes_CHAR_INIT(95), \ + _PyBytes_CHAR_INIT(96), \ + _PyBytes_CHAR_INIT(97), \ + _PyBytes_CHAR_INIT(98), \ + _PyBytes_CHAR_INIT(99), \ + _PyBytes_CHAR_INIT(100), \ + _PyBytes_CHAR_INIT(101), \ + _PyBytes_CHAR_INIT(102), \ + _PyBytes_CHAR_INIT(103), \ + _PyBytes_CHAR_INIT(104), \ + _PyBytes_CHAR_INIT(105), \ + _PyBytes_CHAR_INIT(106), \ + _PyBytes_CHAR_INIT(107), \ + _PyBytes_CHAR_INIT(108), \ + _PyBytes_CHAR_INIT(109), \ + _PyBytes_CHAR_INIT(110), \ + _PyBytes_CHAR_INIT(111), \ + _PyBytes_CHAR_INIT(112), \ + _PyBytes_CHAR_INIT(113), \ + _PyBytes_CHAR_INIT(114), \ + _PyBytes_CHAR_INIT(115), \ + _PyBytes_CHAR_INIT(116), \ + _PyBytes_CHAR_INIT(117), \ + _PyBytes_CHAR_INIT(118), \ + _PyBytes_CHAR_INIT(119), \ + _PyBytes_CHAR_INIT(120), \ + _PyBytes_CHAR_INIT(121), \ + _PyBytes_CHAR_INIT(122), \ + _PyBytes_CHAR_INIT(123), \ + _PyBytes_CHAR_INIT(124), \ + _PyBytes_CHAR_INIT(125), \ + _PyBytes_CHAR_INIT(126), \ + _PyBytes_CHAR_INIT(127), \ + _PyBytes_CHAR_INIT(128), \ + _PyBytes_CHAR_INIT(129), \ + _PyBytes_CHAR_INIT(130), \ + _PyBytes_CHAR_INIT(131), \ + _PyBytes_CHAR_INIT(132), \ + _PyBytes_CHAR_INIT(133), \ + _PyBytes_CHAR_INIT(134), \ + _PyBytes_CHAR_INIT(135), \ + _PyBytes_CHAR_INIT(136), \ + _PyBytes_CHAR_INIT(137), \ + _PyBytes_CHAR_INIT(138), \ + _PyBytes_CHAR_INIT(139), \ + _PyBytes_CHAR_INIT(140), \ + _PyBytes_CHAR_INIT(141), \ + _PyBytes_CHAR_INIT(142), \ + _PyBytes_CHAR_INIT(143), \ + _PyBytes_CHAR_INIT(144), \ + _PyBytes_CHAR_INIT(145), \ + _PyBytes_CHAR_INIT(146), \ + _PyBytes_CHAR_INIT(147), \ + _PyBytes_CHAR_INIT(148), \ + _PyBytes_CHAR_INIT(149), \ + _PyBytes_CHAR_INIT(150), \ + _PyBytes_CHAR_INIT(151), \ + _PyBytes_CHAR_INIT(152), \ + _PyBytes_CHAR_INIT(153), \ + _PyBytes_CHAR_INIT(154), \ + _PyBytes_CHAR_INIT(155), \ + _PyBytes_CHAR_INIT(156), \ + _PyBytes_CHAR_INIT(157), \ + _PyBytes_CHAR_INIT(158), \ + _PyBytes_CHAR_INIT(159), \ + _PyBytes_CHAR_INIT(160), \ + _PyBytes_CHAR_INIT(161), \ + _PyBytes_CHAR_INIT(162), \ + _PyBytes_CHAR_INIT(163), \ + _PyBytes_CHAR_INIT(164), \ + _PyBytes_CHAR_INIT(165), \ + _PyBytes_CHAR_INIT(166), \ + _PyBytes_CHAR_INIT(167), \ + _PyBytes_CHAR_INIT(168), \ + _PyBytes_CHAR_INIT(169), \ + _PyBytes_CHAR_INIT(170), \ + _PyBytes_CHAR_INIT(171), \ + _PyBytes_CHAR_INIT(172), \ + _PyBytes_CHAR_INIT(173), \ + _PyBytes_CHAR_INIT(174), \ + _PyBytes_CHAR_INIT(175), \ + _PyBytes_CHAR_INIT(176), \ + _PyBytes_CHAR_INIT(177), \ + _PyBytes_CHAR_INIT(178), \ + _PyBytes_CHAR_INIT(179), \ + _PyBytes_CHAR_INIT(180), \ + _PyBytes_CHAR_INIT(181), \ + _PyBytes_CHAR_INIT(182), \ + _PyBytes_CHAR_INIT(183), \ + _PyBytes_CHAR_INIT(184), \ + _PyBytes_CHAR_INIT(185), \ + _PyBytes_CHAR_INIT(186), \ + _PyBytes_CHAR_INIT(187), \ + _PyBytes_CHAR_INIT(188), \ + _PyBytes_CHAR_INIT(189), \ + _PyBytes_CHAR_INIT(190), \ + _PyBytes_CHAR_INIT(191), \ + _PyBytes_CHAR_INIT(192), \ + _PyBytes_CHAR_INIT(193), \ + _PyBytes_CHAR_INIT(194), \ + _PyBytes_CHAR_INIT(195), \ + _PyBytes_CHAR_INIT(196), \ + _PyBytes_CHAR_INIT(197), \ + _PyBytes_CHAR_INIT(198), \ + _PyBytes_CHAR_INIT(199), \ + _PyBytes_CHAR_INIT(200), \ + _PyBytes_CHAR_INIT(201), \ + _PyBytes_CHAR_INIT(202), \ + _PyBytes_CHAR_INIT(203), \ + _PyBytes_CHAR_INIT(204), \ + _PyBytes_CHAR_INIT(205), \ + _PyBytes_CHAR_INIT(206), \ + _PyBytes_CHAR_INIT(207), \ + _PyBytes_CHAR_INIT(208), \ + _PyBytes_CHAR_INIT(209), \ + _PyBytes_CHAR_INIT(210), \ + _PyBytes_CHAR_INIT(211), \ + _PyBytes_CHAR_INIT(212), \ + _PyBytes_CHAR_INIT(213), \ + _PyBytes_CHAR_INIT(214), \ + _PyBytes_CHAR_INIT(215), \ + _PyBytes_CHAR_INIT(216), \ + _PyBytes_CHAR_INIT(217), \ + _PyBytes_CHAR_INIT(218), \ + _PyBytes_CHAR_INIT(219), \ + _PyBytes_CHAR_INIT(220), \ + _PyBytes_CHAR_INIT(221), \ + _PyBytes_CHAR_INIT(222), \ + _PyBytes_CHAR_INIT(223), \ + _PyBytes_CHAR_INIT(224), \ + _PyBytes_CHAR_INIT(225), \ + _PyBytes_CHAR_INIT(226), \ + _PyBytes_CHAR_INIT(227), \ + _PyBytes_CHAR_INIT(228), \ + _PyBytes_CHAR_INIT(229), \ + _PyBytes_CHAR_INIT(230), \ + _PyBytes_CHAR_INIT(231), \ + _PyBytes_CHAR_INIT(232), \ + _PyBytes_CHAR_INIT(233), \ + _PyBytes_CHAR_INIT(234), \ + _PyBytes_CHAR_INIT(235), \ + _PyBytes_CHAR_INIT(236), \ + _PyBytes_CHAR_INIT(237), \ + _PyBytes_CHAR_INIT(238), \ + _PyBytes_CHAR_INIT(239), \ + _PyBytes_CHAR_INIT(240), \ + _PyBytes_CHAR_INIT(241), \ + _PyBytes_CHAR_INIT(242), \ + _PyBytes_CHAR_INIT(243), \ + _PyBytes_CHAR_INIT(244), \ + _PyBytes_CHAR_INIT(245), \ + _PyBytes_CHAR_INIT(246), \ + _PyBytes_CHAR_INIT(247), \ + _PyBytes_CHAR_INIT(248), \ + _PyBytes_CHAR_INIT(249), \ + _PyBytes_CHAR_INIT(250), \ + _PyBytes_CHAR_INIT(251), \ + _PyBytes_CHAR_INIT(252), \ + _PyBytes_CHAR_INIT(253), \ + _PyBytes_CHAR_INIT(254), \ + _PyBytes_CHAR_INIT(255), \ + }, \ + \ + .strings = { \ + .literals = { \ + INIT_STR(anon_dictcomp, ""), \ + INIT_STR(anon_genexpr, ""), \ + INIT_STR(anon_lambda, ""), \ + INIT_STR(anon_listcomp, ""), \ + INIT_STR(anon_module, ""), \ + INIT_STR(anon_setcomp, ""), \ + INIT_STR(anon_string, ""), \ + INIT_STR(anon_unknown, ""), \ + INIT_STR(close_br, "}"), \ + INIT_STR(comma_sep, ", "), \ + INIT_STR(dbl_close_br, "}}"), \ + INIT_STR(dbl_open_br, "{{"), \ + INIT_STR(dbl_percent, "%%"), \ + INIT_STR(dot, "."), \ + INIT_STR(dot_locals, "."), \ + INIT_STR(empty, ""), \ + INIT_STR(list_err, "list index out of range"), \ + INIT_STR(newline, "\n"), \ + INIT_STR(open_br, "{"), \ + INIT_STR(percent, "%"), \ + INIT_STR(utf_8, "utf-8"), \ + }, \ + .identifiers = { \ + INIT_ID(False), \ + INIT_ID(Py_Repr), \ + INIT_ID(TextIOWrapper), \ + INIT_ID(True), \ + INIT_ID(WarningMessage), \ + INIT_ID(_), \ + INIT_ID(__IOBase_closed), \ + INIT_ID(__abc_tpflags__), \ + INIT_ID(__abs__), \ + INIT_ID(__abstractmethods__), \ + INIT_ID(__add__), \ + INIT_ID(__aenter__), \ + INIT_ID(__aexit__), \ + INIT_ID(__aiter__), \ + INIT_ID(__all__), \ + INIT_ID(__and__), \ + INIT_ID(__anext__), \ + INIT_ID(__annotations__), \ + INIT_ID(__args__), \ + INIT_ID(__await__), \ + INIT_ID(__bases__), \ + INIT_ID(__bool__), \ + INIT_ID(__build_class__), \ + INIT_ID(__builtins__), \ + INIT_ID(__bytes__), \ + INIT_ID(__call__), \ + INIT_ID(__cantrace__), \ + INIT_ID(__class__), \ + INIT_ID(__class_getitem__), \ + INIT_ID(__classcell__), \ + INIT_ID(__complex__), \ + INIT_ID(__contains__), \ + INIT_ID(__copy__), \ + INIT_ID(__del__), \ + INIT_ID(__delattr__), \ + INIT_ID(__delete__), \ + INIT_ID(__delitem__), \ + INIT_ID(__dict__), \ + INIT_ID(__dir__), \ + INIT_ID(__divmod__), \ + INIT_ID(__doc__), \ + INIT_ID(__enter__), \ + INIT_ID(__eq__), \ + INIT_ID(__exit__), \ + INIT_ID(__file__), \ + INIT_ID(__float__), \ + INIT_ID(__floordiv__), \ + INIT_ID(__format__), \ + INIT_ID(__fspath__), \ + INIT_ID(__ge__), \ + INIT_ID(__get__), \ + INIT_ID(__getattr__), \ + INIT_ID(__getattribute__), \ + INIT_ID(__getinitargs__), \ + INIT_ID(__getitem__), \ + INIT_ID(__getnewargs__), \ + INIT_ID(__getnewargs_ex__), \ + INIT_ID(__getstate__), \ + INIT_ID(__gt__), \ + INIT_ID(__hash__), \ + INIT_ID(__iadd__), \ + INIT_ID(__iand__), \ + INIT_ID(__ifloordiv__), \ + INIT_ID(__ilshift__), \ + INIT_ID(__imatmul__), \ + INIT_ID(__imod__), \ + INIT_ID(__import__), \ + INIT_ID(__imul__), \ + INIT_ID(__index__), \ + INIT_ID(__init__), \ + INIT_ID(__init_subclass__), \ + INIT_ID(__instancecheck__), \ + INIT_ID(__int__), \ + INIT_ID(__invert__), \ + INIT_ID(__ior__), \ + INIT_ID(__ipow__), \ + INIT_ID(__irshift__), \ + INIT_ID(__isabstractmethod__), \ + INIT_ID(__isub__), \ + INIT_ID(__iter__), \ + INIT_ID(__itruediv__), \ + INIT_ID(__ixor__), \ + INIT_ID(__le__), \ + INIT_ID(__len__), \ + INIT_ID(__length_hint__), \ + INIT_ID(__lltrace__), \ + INIT_ID(__loader__), \ + INIT_ID(__lshift__), \ + INIT_ID(__lt__), \ + INIT_ID(__main__), \ + INIT_ID(__matmul__), \ + INIT_ID(__missing__), \ + INIT_ID(__mod__), \ + INIT_ID(__module__), \ + INIT_ID(__mro_entries__), \ + INIT_ID(__mul__), \ + INIT_ID(__name__), \ + INIT_ID(__ne__), \ + INIT_ID(__neg__), \ + INIT_ID(__new__), \ + INIT_ID(__newobj__), \ + INIT_ID(__newobj_ex__), \ + INIT_ID(__next__), \ + INIT_ID(__notes__), \ + INIT_ID(__or__), \ + INIT_ID(__orig_class__), \ + INIT_ID(__origin__), \ + INIT_ID(__package__), \ + INIT_ID(__parameters__), \ + INIT_ID(__path__), \ + INIT_ID(__pos__), \ + INIT_ID(__pow__), \ + INIT_ID(__prepare__), \ + INIT_ID(__qualname__), \ + INIT_ID(__radd__), \ + INIT_ID(__rand__), \ + INIT_ID(__rdivmod__), \ + INIT_ID(__reduce__), \ + INIT_ID(__reduce_ex__), \ + INIT_ID(__repr__), \ + INIT_ID(__reversed__), \ + INIT_ID(__rfloordiv__), \ + INIT_ID(__rlshift__), \ + INIT_ID(__rmatmul__), \ + INIT_ID(__rmod__), \ + INIT_ID(__rmul__), \ + INIT_ID(__ror__), \ + INIT_ID(__round__), \ + INIT_ID(__rpow__), \ + INIT_ID(__rrshift__), \ + INIT_ID(__rshift__), \ + INIT_ID(__rsub__), \ + INIT_ID(__rtruediv__), \ + INIT_ID(__rxor__), \ + INIT_ID(__set__), \ + INIT_ID(__set_name__), \ + INIT_ID(__setattr__), \ + INIT_ID(__setitem__), \ + INIT_ID(__setstate__), \ + INIT_ID(__sizeof__), \ + INIT_ID(__slotnames__), \ + INIT_ID(__slots__), \ + INIT_ID(__spec__), \ + INIT_ID(__str__), \ + INIT_ID(__sub__), \ + INIT_ID(__subclasscheck__), \ + INIT_ID(__subclasshook__), \ + INIT_ID(__truediv__), \ + INIT_ID(__trunc__), \ + INIT_ID(__typing_is_unpacked_typevartuple__), \ + INIT_ID(__typing_prepare_subst__), \ + INIT_ID(__typing_subst__), \ + INIT_ID(__typing_unpacked_tuple_args__), \ + INIT_ID(__warningregistry__), \ + INIT_ID(__weakref__), \ + INIT_ID(__xor__), \ + INIT_ID(_abc_impl), \ + INIT_ID(_annotation), \ + INIT_ID(_blksize), \ + INIT_ID(_bootstrap), \ + INIT_ID(_dealloc_warn), \ + INIT_ID(_finalizing), \ + INIT_ID(_find_and_load), \ + INIT_ID(_fix_up_module), \ + INIT_ID(_get_sourcefile), \ + INIT_ID(_handle_fromlist), \ + INIT_ID(_initializing), \ + INIT_ID(_is_text_encoding), \ + INIT_ID(_lock_unlock_module), \ + INIT_ID(_showwarnmsg), \ + INIT_ID(_shutdown), \ + INIT_ID(_slotnames), \ + INIT_ID(_strptime_time), \ + INIT_ID(_uninitialized_submodules), \ + INIT_ID(_warn_unawaited_coroutine), \ + INIT_ID(_xoptions), \ + INIT_ID(add), \ + INIT_ID(append), \ + INIT_ID(big), \ + INIT_ID(buffer), \ + INIT_ID(builtins), \ + INIT_ID(c_call), \ + INIT_ID(c_exception), \ + INIT_ID(c_return), \ + INIT_ID(call), \ + INIT_ID(clear), \ + INIT_ID(close), \ + INIT_ID(closed), \ + INIT_ID(code), \ + INIT_ID(copy), \ + INIT_ID(copyreg), \ + INIT_ID(decode), \ + INIT_ID(default), \ + INIT_ID(defaultaction), \ + INIT_ID(dictcomp), \ + INIT_ID(difference_update), \ + INIT_ID(dispatch_table), \ + INIT_ID(displayhook), \ + INIT_ID(enable), \ + INIT_ID(encode), \ + INIT_ID(encoding), \ + INIT_ID(end_lineno), \ + INIT_ID(end_offset), \ + INIT_ID(errors), \ + INIT_ID(excepthook), \ + INIT_ID(exception), \ + INIT_ID(extend), \ + INIT_ID(filename), \ + INIT_ID(fileno), \ + INIT_ID(fillvalue), \ + INIT_ID(filters), \ + INIT_ID(find_class), \ + INIT_ID(flush), \ + INIT_ID(genexpr), \ + INIT_ID(get), \ + INIT_ID(get_source), \ + INIT_ID(getattr), \ + INIT_ID(getstate), \ + INIT_ID(ignore), \ + INIT_ID(importlib), \ + INIT_ID(inf), \ + INIT_ID(intersection), \ + INIT_ID(isatty), \ + INIT_ID(isinstance), \ + INIT_ID(items), \ + INIT_ID(iter), \ + INIT_ID(join), \ + INIT_ID(keys), \ + INIT_ID(lambda), \ + INIT_ID(last_traceback), \ + INIT_ID(last_type), \ + INIT_ID(last_value), \ + INIT_ID(latin1), \ + INIT_ID(len), \ + INIT_ID(line), \ + INIT_ID(lineno), \ + INIT_ID(listcomp), \ + INIT_ID(little), \ + INIT_ID(locale), \ + INIT_ID(match), \ + INIT_ID(metaclass), \ + INIT_ID(mode), \ + INIT_ID(modules), \ + INIT_ID(mro), \ + INIT_ID(msg), \ + INIT_ID(n_fields), \ + INIT_ID(n_sequence_fields), \ + INIT_ID(n_unnamed_fields), \ + INIT_ID(name), \ + INIT_ID(newlines), \ + INIT_ID(next), \ + INIT_ID(obj), \ + INIT_ID(offset), \ + INIT_ID(onceregistry), \ + INIT_ID(opcode), \ + INIT_ID(open), \ + INIT_ID(parent), \ + INIT_ID(partial), \ + INIT_ID(path), \ + INIT_ID(peek), \ + INIT_ID(persistent_id), \ + INIT_ID(persistent_load), \ + INIT_ID(print_file_and_line), \ + INIT_ID(ps1), \ + INIT_ID(ps2), \ + INIT_ID(raw), \ + INIT_ID(read), \ + INIT_ID(read1), \ + INIT_ID(readable), \ + INIT_ID(readall), \ + INIT_ID(readinto), \ + INIT_ID(readinto1), \ + INIT_ID(readline), \ + INIT_ID(reducer_override), \ + INIT_ID(reload), \ + INIT_ID(replace), \ + INIT_ID(reset), \ + INIT_ID(return), \ + INIT_ID(reversed), \ + INIT_ID(seek), \ + INIT_ID(seekable), \ + INIT_ID(send), \ + INIT_ID(setcomp), \ + INIT_ID(setstate), \ + INIT_ID(sort), \ + INIT_ID(stderr), \ + INIT_ID(stdin), \ + INIT_ID(stdout), \ + INIT_ID(strict), \ + INIT_ID(symmetric_difference_update), \ + INIT_ID(tell), \ + INIT_ID(text), \ + INIT_ID(threading), \ + INIT_ID(throw), \ + INIT_ID(top), \ + INIT_ID(truncate), \ + INIT_ID(unraisablehook), \ + INIT_ID(values), \ + INIT_ID(version), \ + INIT_ID(warnings), \ + INIT_ID(warnoptions), \ + INIT_ID(writable), \ + INIT_ID(write), \ + INIT_ID(zipimporter), \ + }, \ + .ascii = { \ + _PyASCIIObject_INIT("\x00"), \ + _PyASCIIObject_INIT("\x01"), \ + _PyASCIIObject_INIT("\x02"), \ + _PyASCIIObject_INIT("\x03"), \ + _PyASCIIObject_INIT("\x04"), \ + _PyASCIIObject_INIT("\x05"), \ + _PyASCIIObject_INIT("\x06"), \ + _PyASCIIObject_INIT("\x07"), \ + _PyASCIIObject_INIT("\x08"), \ + _PyASCIIObject_INIT("\x09"), \ + _PyASCIIObject_INIT("\x0a"), \ + _PyASCIIObject_INIT("\x0b"), \ + _PyASCIIObject_INIT("\x0c"), \ + _PyASCIIObject_INIT("\x0d"), \ + _PyASCIIObject_INIT("\x0e"), \ + _PyASCIIObject_INIT("\x0f"), \ + _PyASCIIObject_INIT("\x10"), \ + _PyASCIIObject_INIT("\x11"), \ + _PyASCIIObject_INIT("\x12"), \ + _PyASCIIObject_INIT("\x13"), \ + _PyASCIIObject_INIT("\x14"), \ + _PyASCIIObject_INIT("\x15"), \ + _PyASCIIObject_INIT("\x16"), \ + _PyASCIIObject_INIT("\x17"), \ + _PyASCIIObject_INIT("\x18"), \ + _PyASCIIObject_INIT("\x19"), \ + _PyASCIIObject_INIT("\x1a"), \ + _PyASCIIObject_INIT("\x1b"), \ + _PyASCIIObject_INIT("\x1c"), \ + _PyASCIIObject_INIT("\x1d"), \ + _PyASCIIObject_INIT("\x1e"), \ + _PyASCIIObject_INIT("\x1f"), \ + _PyASCIIObject_INIT("\x20"), \ + _PyASCIIObject_INIT("\x21"), \ + _PyASCIIObject_INIT("\x22"), \ + _PyASCIIObject_INIT("\x23"), \ + _PyASCIIObject_INIT("\x24"), \ + _PyASCIIObject_INIT("\x25"), \ + _PyASCIIObject_INIT("\x26"), \ + _PyASCIIObject_INIT("\x27"), \ + _PyASCIIObject_INIT("\x28"), \ + _PyASCIIObject_INIT("\x29"), \ + _PyASCIIObject_INIT("\x2a"), \ + _PyASCIIObject_INIT("\x2b"), \ + _PyASCIIObject_INIT("\x2c"), \ + _PyASCIIObject_INIT("\x2d"), \ + _PyASCIIObject_INIT("\x2e"), \ + _PyASCIIObject_INIT("\x2f"), \ + _PyASCIIObject_INIT("\x30"), \ + _PyASCIIObject_INIT("\x31"), \ + _PyASCIIObject_INIT("\x32"), \ + _PyASCIIObject_INIT("\x33"), \ + _PyASCIIObject_INIT("\x34"), \ + _PyASCIIObject_INIT("\x35"), \ + _PyASCIIObject_INIT("\x36"), \ + _PyASCIIObject_INIT("\x37"), \ + _PyASCIIObject_INIT("\x38"), \ + _PyASCIIObject_INIT("\x39"), \ + _PyASCIIObject_INIT("\x3a"), \ + _PyASCIIObject_INIT("\x3b"), \ + _PyASCIIObject_INIT("\x3c"), \ + _PyASCIIObject_INIT("\x3d"), \ + _PyASCIIObject_INIT("\x3e"), \ + _PyASCIIObject_INIT("\x3f"), \ + _PyASCIIObject_INIT("\x40"), \ + _PyASCIIObject_INIT("\x41"), \ + _PyASCIIObject_INIT("\x42"), \ + _PyASCIIObject_INIT("\x43"), \ + _PyASCIIObject_INIT("\x44"), \ + _PyASCIIObject_INIT("\x45"), \ + _PyASCIIObject_INIT("\x46"), \ + _PyASCIIObject_INIT("\x47"), \ + _PyASCIIObject_INIT("\x48"), \ + _PyASCIIObject_INIT("\x49"), \ + _PyASCIIObject_INIT("\x4a"), \ + _PyASCIIObject_INIT("\x4b"), \ + _PyASCIIObject_INIT("\x4c"), \ + _PyASCIIObject_INIT("\x4d"), \ + _PyASCIIObject_INIT("\x4e"), \ + _PyASCIIObject_INIT("\x4f"), \ + _PyASCIIObject_INIT("\x50"), \ + _PyASCIIObject_INIT("\x51"), \ + _PyASCIIObject_INIT("\x52"), \ + _PyASCIIObject_INIT("\x53"), \ + _PyASCIIObject_INIT("\x54"), \ + _PyASCIIObject_INIT("\x55"), \ + _PyASCIIObject_INIT("\x56"), \ + _PyASCIIObject_INIT("\x57"), \ + _PyASCIIObject_INIT("\x58"), \ + _PyASCIIObject_INIT("\x59"), \ + _PyASCIIObject_INIT("\x5a"), \ + _PyASCIIObject_INIT("\x5b"), \ + _PyASCIIObject_INIT("\x5c"), \ + _PyASCIIObject_INIT("\x5d"), \ + _PyASCIIObject_INIT("\x5e"), \ + _PyASCIIObject_INIT("\x5f"), \ + _PyASCIIObject_INIT("\x60"), \ + _PyASCIIObject_INIT("\x61"), \ + _PyASCIIObject_INIT("\x62"), \ + _PyASCIIObject_INIT("\x63"), \ + _PyASCIIObject_INIT("\x64"), \ + _PyASCIIObject_INIT("\x65"), \ + _PyASCIIObject_INIT("\x66"), \ + _PyASCIIObject_INIT("\x67"), \ + _PyASCIIObject_INIT("\x68"), \ + _PyASCIIObject_INIT("\x69"), \ + _PyASCIIObject_INIT("\x6a"), \ + _PyASCIIObject_INIT("\x6b"), \ + _PyASCIIObject_INIT("\x6c"), \ + _PyASCIIObject_INIT("\x6d"), \ + _PyASCIIObject_INIT("\x6e"), \ + _PyASCIIObject_INIT("\x6f"), \ + _PyASCIIObject_INIT("\x70"), \ + _PyASCIIObject_INIT("\x71"), \ + _PyASCIIObject_INIT("\x72"), \ + _PyASCIIObject_INIT("\x73"), \ + _PyASCIIObject_INIT("\x74"), \ + _PyASCIIObject_INIT("\x75"), \ + _PyASCIIObject_INIT("\x76"), \ + _PyASCIIObject_INIT("\x77"), \ + _PyASCIIObject_INIT("\x78"), \ + _PyASCIIObject_INIT("\x79"), \ + _PyASCIIObject_INIT("\x7a"), \ + _PyASCIIObject_INIT("\x7b"), \ + _PyASCIIObject_INIT("\x7c"), \ + _PyASCIIObject_INIT("\x7d"), \ + _PyASCIIObject_INIT("\x7e"), \ + _PyASCIIObject_INIT("\x7f"), \ + }, \ + .latin1 = { \ + _PyUnicode_LATIN1_INIT("\x80"), \ + _PyUnicode_LATIN1_INIT("\x81"), \ + _PyUnicode_LATIN1_INIT("\x82"), \ + _PyUnicode_LATIN1_INIT("\x83"), \ + _PyUnicode_LATIN1_INIT("\x84"), \ + _PyUnicode_LATIN1_INIT("\x85"), \ + _PyUnicode_LATIN1_INIT("\x86"), \ + _PyUnicode_LATIN1_INIT("\x87"), \ + _PyUnicode_LATIN1_INIT("\x88"), \ + _PyUnicode_LATIN1_INIT("\x89"), \ + _PyUnicode_LATIN1_INIT("\x8a"), \ + _PyUnicode_LATIN1_INIT("\x8b"), \ + _PyUnicode_LATIN1_INIT("\x8c"), \ + _PyUnicode_LATIN1_INIT("\x8d"), \ + _PyUnicode_LATIN1_INIT("\x8e"), \ + _PyUnicode_LATIN1_INIT("\x8f"), \ + _PyUnicode_LATIN1_INIT("\x90"), \ + _PyUnicode_LATIN1_INIT("\x91"), \ + _PyUnicode_LATIN1_INIT("\x92"), \ + _PyUnicode_LATIN1_INIT("\x93"), \ + _PyUnicode_LATIN1_INIT("\x94"), \ + _PyUnicode_LATIN1_INIT("\x95"), \ + _PyUnicode_LATIN1_INIT("\x96"), \ + _PyUnicode_LATIN1_INIT("\x97"), \ + _PyUnicode_LATIN1_INIT("\x98"), \ + _PyUnicode_LATIN1_INIT("\x99"), \ + _PyUnicode_LATIN1_INIT("\x9a"), \ + _PyUnicode_LATIN1_INIT("\x9b"), \ + _PyUnicode_LATIN1_INIT("\x9c"), \ + _PyUnicode_LATIN1_INIT("\x9d"), \ + _PyUnicode_LATIN1_INIT("\x9e"), \ + _PyUnicode_LATIN1_INIT("\x9f"), \ + _PyUnicode_LATIN1_INIT("\xa0"), \ + _PyUnicode_LATIN1_INIT("\xa1"), \ + _PyUnicode_LATIN1_INIT("\xa2"), \ + _PyUnicode_LATIN1_INIT("\xa3"), \ + _PyUnicode_LATIN1_INIT("\xa4"), \ + _PyUnicode_LATIN1_INIT("\xa5"), \ + _PyUnicode_LATIN1_INIT("\xa6"), \ + _PyUnicode_LATIN1_INIT("\xa7"), \ + _PyUnicode_LATIN1_INIT("\xa8"), \ + _PyUnicode_LATIN1_INIT("\xa9"), \ + _PyUnicode_LATIN1_INIT("\xaa"), \ + _PyUnicode_LATIN1_INIT("\xab"), \ + _PyUnicode_LATIN1_INIT("\xac"), \ + _PyUnicode_LATIN1_INIT("\xad"), \ + _PyUnicode_LATIN1_INIT("\xae"), \ + _PyUnicode_LATIN1_INIT("\xaf"), \ + _PyUnicode_LATIN1_INIT("\xb0"), \ + _PyUnicode_LATIN1_INIT("\xb1"), \ + _PyUnicode_LATIN1_INIT("\xb2"), \ + _PyUnicode_LATIN1_INIT("\xb3"), \ + _PyUnicode_LATIN1_INIT("\xb4"), \ + _PyUnicode_LATIN1_INIT("\xb5"), \ + _PyUnicode_LATIN1_INIT("\xb6"), \ + _PyUnicode_LATIN1_INIT("\xb7"), \ + _PyUnicode_LATIN1_INIT("\xb8"), \ + _PyUnicode_LATIN1_INIT("\xb9"), \ + _PyUnicode_LATIN1_INIT("\xba"), \ + _PyUnicode_LATIN1_INIT("\xbb"), \ + _PyUnicode_LATIN1_INIT("\xbc"), \ + _PyUnicode_LATIN1_INIT("\xbd"), \ + _PyUnicode_LATIN1_INIT("\xbe"), \ + _PyUnicode_LATIN1_INIT("\xbf"), \ + _PyUnicode_LATIN1_INIT("\xc0"), \ + _PyUnicode_LATIN1_INIT("\xc1"), \ + _PyUnicode_LATIN1_INIT("\xc2"), \ + _PyUnicode_LATIN1_INIT("\xc3"), \ + _PyUnicode_LATIN1_INIT("\xc4"), \ + _PyUnicode_LATIN1_INIT("\xc5"), \ + _PyUnicode_LATIN1_INIT("\xc6"), \ + _PyUnicode_LATIN1_INIT("\xc7"), \ + _PyUnicode_LATIN1_INIT("\xc8"), \ + _PyUnicode_LATIN1_INIT("\xc9"), \ + _PyUnicode_LATIN1_INIT("\xca"), \ + _PyUnicode_LATIN1_INIT("\xcb"), \ + _PyUnicode_LATIN1_INIT("\xcc"), \ + _PyUnicode_LATIN1_INIT("\xcd"), \ + _PyUnicode_LATIN1_INIT("\xce"), \ + _PyUnicode_LATIN1_INIT("\xcf"), \ + _PyUnicode_LATIN1_INIT("\xd0"), \ + _PyUnicode_LATIN1_INIT("\xd1"), \ + _PyUnicode_LATIN1_INIT("\xd2"), \ + _PyUnicode_LATIN1_INIT("\xd3"), \ + _PyUnicode_LATIN1_INIT("\xd4"), \ + _PyUnicode_LATIN1_INIT("\xd5"), \ + _PyUnicode_LATIN1_INIT("\xd6"), \ + _PyUnicode_LATIN1_INIT("\xd7"), \ + _PyUnicode_LATIN1_INIT("\xd8"), \ + _PyUnicode_LATIN1_INIT("\xd9"), \ + _PyUnicode_LATIN1_INIT("\xda"), \ + _PyUnicode_LATIN1_INIT("\xdb"), \ + _PyUnicode_LATIN1_INIT("\xdc"), \ + _PyUnicode_LATIN1_INIT("\xdd"), \ + _PyUnicode_LATIN1_INIT("\xde"), \ + _PyUnicode_LATIN1_INIT("\xdf"), \ + _PyUnicode_LATIN1_INIT("\xe0"), \ + _PyUnicode_LATIN1_INIT("\xe1"), \ + _PyUnicode_LATIN1_INIT("\xe2"), \ + _PyUnicode_LATIN1_INIT("\xe3"), \ + _PyUnicode_LATIN1_INIT("\xe4"), \ + _PyUnicode_LATIN1_INIT("\xe5"), \ + _PyUnicode_LATIN1_INIT("\xe6"), \ + _PyUnicode_LATIN1_INIT("\xe7"), \ + _PyUnicode_LATIN1_INIT("\xe8"), \ + _PyUnicode_LATIN1_INIT("\xe9"), \ + _PyUnicode_LATIN1_INIT("\xea"), \ + _PyUnicode_LATIN1_INIT("\xeb"), \ + _PyUnicode_LATIN1_INIT("\xec"), \ + _PyUnicode_LATIN1_INIT("\xed"), \ + _PyUnicode_LATIN1_INIT("\xee"), \ + _PyUnicode_LATIN1_INIT("\xef"), \ + _PyUnicode_LATIN1_INIT("\xf0"), \ + _PyUnicode_LATIN1_INIT("\xf1"), \ + _PyUnicode_LATIN1_INIT("\xf2"), \ + _PyUnicode_LATIN1_INIT("\xf3"), \ + _PyUnicode_LATIN1_INIT("\xf4"), \ + _PyUnicode_LATIN1_INIT("\xf5"), \ + _PyUnicode_LATIN1_INIT("\xf6"), \ + _PyUnicode_LATIN1_INIT("\xf7"), \ + _PyUnicode_LATIN1_INIT("\xf8"), \ + _PyUnicode_LATIN1_INIT("\xf9"), \ + _PyUnicode_LATIN1_INIT("\xfa"), \ + _PyUnicode_LATIN1_INIT("\xfb"), \ + _PyUnicode_LATIN1_INIT("\xfc"), \ + _PyUnicode_LATIN1_INIT("\xfd"), \ + _PyUnicode_LATIN1_INIT("\xfe"), \ + _PyUnicode_LATIN1_INIT("\xff"), \ + }, \ + }, \ + \ + .tuple_empty = { \ + .ob_base = _PyVarObject_IMMORTAL_INIT(&PyTuple_Type, 0) \ + }, \ + }, \ +} +/* End auto-generated code */ + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_RUNTIME_INIT_H */ diff --git a/include/internal/pycore_signal.h b/include/internal/pycore_signal.h new file mode 100644 index 00000000..b921dd17 --- /dev/null +++ b/include/internal/pycore_signal.h @@ -0,0 +1,35 @@ +// Define Py_NSIG constant for signal handling. + +#ifndef Py_INTERNAL_SIGNAL_H +#define Py_INTERNAL_SIGNAL_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include // NSIG + +#ifdef _SIG_MAXSIG + // gh-91145: On FreeBSD, defines NSIG as 32: it doesn't include + // realtime signals: [SIGRTMIN,SIGRTMAX]. Use _SIG_MAXSIG instead. For + // example on x86-64 FreeBSD 13, SIGRTMAX is 126 and _SIG_MAXSIG is 128. +# define Py_NSIG _SIG_MAXSIG +#elif defined(NSIG) +# define Py_NSIG NSIG +#elif defined(_NSIG) +# define Py_NSIG _NSIG // BSD/SysV +#elif defined(_SIGMAX) +# define Py_NSIG (_SIGMAX + 1) // QNX +#elif defined(SIGMAX) +# define Py_NSIG (SIGMAX + 1) // djgpp +#else +# define Py_NSIG 64 // Use a reasonable default value +#endif + +#ifdef __cplusplus +} +#endif +#endif // !Py_INTERNAL_SIGNAL_H diff --git a/include/internal/pycore_sliceobject.h b/include/internal/pycore_sliceobject.h new file mode 100644 index 00000000..e81834c0 --- /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_strhex.h b/include/internal/pycore_strhex.h new file mode 100644 index 00000000..f427b4d6 --- /dev/null +++ b/include/internal/pycore_strhex.h @@ -0,0 +1,36 @@ +#ifndef Py_INTERNAL_STRHEX_H +#define Py_INTERNAL_STRHEX_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +// Returns a str() containing the hex representation of argbuf. +PyAPI_FUNC(PyObject*) _Py_strhex(const + char* argbuf, + const Py_ssize_t arglen); + +// Returns a bytes() containing the ASCII hex representation of argbuf. +PyAPI_FUNC(PyObject*) _Py_strhex_bytes( + const char* argbuf, + const Py_ssize_t arglen); + +// These variants include support for a separator between every N bytes: +PyAPI_FUNC(PyObject*) _Py_strhex_with_sep( + const char* argbuf, + const Py_ssize_t arglen, + PyObject* sep, + const int bytes_per_group); +PyAPI_FUNC(PyObject*) _Py_strhex_bytes_with_sep( + const char* argbuf, + const Py_ssize_t arglen, + PyObject* sep, + const int bytes_per_group); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_STRHEX_H */ diff --git a/include/internal/pycore_structseq.h b/include/internal/pycore_structseq.h index 84c8d477..0199c790 100644 --- a/include/internal/pycore_structseq.h +++ b/include/internal/pycore_structseq.h @@ -9,11 +9,18 @@ extern "C" { #endif +/* other API */ + +PyAPI_FUNC(PyTypeObject *) _PyStructSequence_NewType( + PyStructSequence_Desc *desc, + unsigned long tp_flags); + PyAPI_FUNC(int) _PyStructSequence_InitType( PyTypeObject *type, PyStructSequence_Desc *desc, unsigned long tp_flags); +extern void _PyStructSequence_FiniType(PyTypeObject *type); #ifdef __cplusplus } diff --git a/include/internal/pycore_symtable.h b/include/internal/pycore_symtable.h index a2e520b8..28935f4e 100644 --- a/include/internal/pycore_symtable.h +++ b/include/internal/pycore_symtable.h @@ -79,6 +79,7 @@ extern PyTypeObject PySTEntry_Type; #define PySTEntry_Check(op) Py_IS_TYPE(op, &PySTEntry_Type) +extern long _PyST_GetSymbol(PySTEntryObject *, PyObject *); extern int _PyST_GetScope(PySTEntryObject *, PyObject *); extern struct symtable* _PySymtable_Build( diff --git a/include/internal/pycore_sysmodule.h b/include/internal/pycore_sysmodule.h index 738a7746..10d092cd 100644 --- a/include/internal/pycore_sysmodule.h +++ b/include/internal/pycore_sysmodule.h @@ -18,6 +18,8 @@ PyAPI_FUNC(int) _PySys_Audit( PyAPI_FUNC() to not export the symbol. */ extern void _PySys_ClearAuditHooks(PyThreadState *tstate); +PyAPI_FUNC(int) _PySys_SetAttr(PyObject *, PyObject *); + #ifdef __cplusplus } #endif diff --git a/include/internal/pycore_traceback.h b/include/internal/pycore_traceback.h index c01a4763..c393b2c1 100644 --- a/include/internal/pycore_traceback.h +++ b/include/internal/pycore_traceback.h @@ -8,9 +8,6 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -/* Forward declaration */ -struct _is; - /* Write the Python traceback into the file 'fd'. For example: Traceback (most recent call first): @@ -57,7 +54,7 @@ PyAPI_FUNC(void) _Py_DumpTraceback( PyAPI_FUNC(const char*) _Py_DumpTracebackThreads( int fd, - struct _is *interp, + PyInterpreterState *interp, PyThreadState *current_tstate); /* Write a Unicode object into the file descriptor fd. Encode the string to @@ -87,6 +84,17 @@ PyAPI_FUNC(PyObject*) _PyTraceBack_FromFrame( PyObject *tb_next, PyFrameObject *frame); +#define EXCEPTION_TB_HEADER "Traceback (most recent call last):\n" +#define EXCEPTION_GROUP_TB_HEADER "Exception Group Traceback (most recent call last):\n" + +/* Write the traceback tb to file f. Prefix each line with + indent spaces followed by the margin (if it is not NULL). */ +PyAPI_FUNC(int) _PyTraceBack_Print_Indented( + PyObject *tb, int indent, const char* margin, + const char *header_margin, const char *header, PyObject *f); +PyAPI_FUNC(int) _Py_WriteIndentedMargin(int, const char*, PyObject *); +PyAPI_FUNC(int) _Py_WriteIndent(int, PyObject *); + #ifdef __cplusplus } #endif diff --git a/include/internal/pycore_tuple.h b/include/internal/pycore_tuple.h index 5353e18d..1efe4fa2 100644 --- a/include/internal/pycore_tuple.h +++ b/include/internal/pycore_tuple.h @@ -10,9 +10,62 @@ 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 */ + +// PyTuple_MAXSAVESIZE - largest tuple to save on free list +// PyTuple_MAXFREELIST - maximum number of tuples of each size to save + +#if defined(PyTuple_MAXSAVESIZE) && PyTuple_MAXSAVESIZE <= 0 + // A build indicated that tuple freelists should not be used. +# define PyTuple_NFREELISTS 0 +# undef PyTuple_MAXSAVESIZE +# undef PyTuple_MAXFREELIST + +#elif !defined(WITH_FREELISTS) +# define PyTuple_NFREELISTS 0 +# undef PyTuple_MAXSAVESIZE +# undef PyTuple_MAXFREELIST + +#else + // We are using a freelist for tuples. +# ifndef PyTuple_MAXSAVESIZE +# define PyTuple_MAXSAVESIZE 20 +# endif +# define PyTuple_NFREELISTS PyTuple_MAXSAVESIZE +# ifndef PyTuple_MAXFREELIST +# define PyTuple_MAXFREELIST 2000 +# endif +#endif + +struct _Py_tuple_state { +#if PyTuple_NFREELISTS > 0 + /* There is one freelist for each size from 1 to PyTuple_MAXSAVESIZE. + The empty tuple is handled separately. + + Each tuple stored in the array is the head of the linked list + (and the next available tuple) for that size. The actual tuple + object is used as the linked list node, with its first item + (ob_item[0]) pointing to the next node (i.e. the previous head). + Each linked list is initially NULL. */ + PyTupleObject *free_list[PyTuple_NFREELISTS]; + int numfree[PyTuple_NFREELISTS]; +#else + char _unused; // Empty structs are not allowed. +#endif +}; + #define _PyTuple_ITEMS(op) (_PyTuple_CAST(op)->ob_item) -PyAPI_FUNC(PyObject *) _PyTuple_FromArray(PyObject *const *, Py_ssize_t); +extern PyObject *_PyTuple_FromArray(PyObject *const *, Py_ssize_t); +extern PyObject *_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t); #ifdef __cplusplus } diff --git a/include/internal/pycore_typeobject.h b/include/internal/pycore_typeobject.h new file mode 100644 index 00000000..c480a3a5 --- /dev/null +++ b/include/internal/pycore_typeobject.h @@ -0,0 +1,50 @@ +#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_FiniTypes(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); + +extern void _PyStaticType_Dealloc(PyTypeObject *type); + + +#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 00000000..4bee2419 --- /dev/null +++ b/include/internal/pycore_unicodeobject.h @@ -0,0 +1,62 @@ +#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 + +#include "pycore_fileutils.h" // _Py_error_handler + +void _PyUnicode_ExactDealloc(PyObject *op); + +/* runtime lifecycle */ + +extern void _PyUnicode_InitState(PyInterpreterState *); +extern PyStatus _PyUnicode_InitGlobalObjects(PyInterpreterState *); +extern PyStatus _PyUnicode_InitTypes(PyInterpreterState *); +extern void _PyUnicode_Fini(PyInterpreterState *); +extern void _PyUnicode_FiniTypes(PyInterpreterState *); +extern void _PyStaticUnicode_Dealloc(PyObject *); + +extern PyTypeObject _PyUnicodeASCIIIter_Type; + +/* 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 { + struct _Py_unicode_fs_codec fs_codec; + + // Unicode identifiers (_Py_Identifier): see _PyUnicode_FromId() + struct _Py_unicode_ids ids; +}; + +extern void _PyUnicode_ClearInterned(PyInterpreterState *interp); + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_UNICODEOBJECT_H */ diff --git a/include/internal/pycore_unionobject.h b/include/internal/pycore_unionobject.h index 9962f576..a9ed5651 100644 --- a/include/internal/pycore_unionobject.h +++ b/include/internal/pycore_unionobject.h @@ -15,6 +15,7 @@ extern PyObject *_Py_union_type_or(PyObject *, PyObject *); #define _PyGenericAlias_Check(op) PyObject_TypeCheck(op, &Py_GenericAliasType) extern PyObject *_Py_subs_parameters(PyObject *, PyObject *, PyObject *, PyObject *); extern PyObject *_Py_make_parameters(PyObject *); +extern PyObject *_Py_union_args(PyObject *self); #ifdef __cplusplus } diff --git a/include/internal/pycore_warnings.h b/include/internal/pycore_warnings.h index f728ec30..efb4f1cd 100644 --- a/include/internal/pycore_warnings.h +++ b/include/internal/pycore_warnings.h @@ -19,6 +19,10 @@ struct _warnings_runtime_state { extern int _PyWarnings_InitState(PyInterpreterState *interp); +PyAPI_FUNC(PyObject*) _PyWarnings_Init(void); + +extern void _PyErr_WarnUnawaitedCoroutine(PyObject *coro); + #ifdef __cplusplus } #endif diff --git a/include/interpreteridobject.h b/include/interpreteridobject.h deleted file mode 100644 index e744fcdc..00000000 --- a/include/interpreteridobject.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef Py_INTERPRETERIDOBJECT_H -#define Py_INTERPRETERIDOBJECT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef Py_LIMITED_API -# define Py_CPYTHON_INTERPRETERIDOBJECT_H -# include "cpython/interpreteridobject.h" -# undef Py_CPYTHON_INTERPRETERIDOBJECT_H -#endif - -#ifdef __cplusplus -} -#endif -#endif /* !Py_INTERPRETERIDOBJECT_H */ diff --git a/include/listobject.h b/include/listobject.h index 2a8a2552..eff42c18 100644 --- a/include/listobject.h +++ b/include/listobject.h @@ -42,7 +42,7 @@ PyAPI_FUNC(PyObject *) PyList_AsTuple(PyObject *); #ifndef Py_LIMITED_API # define Py_CPYTHON_LISTOBJECT_H -# include "cpython/listobject.h" +# include "cpython/listobject.h" # undef Py_CPYTHON_LISTOBJECT_H #endif diff --git a/include/longobject.h b/include/longobject.h index e2301d7a..81ba1239 100644 --- a/include/longobject.h +++ b/include/longobject.h @@ -7,8 +7,6 @@ extern "C" { /* Long (arbitrary precision) integer object interface */ -typedef struct _longobject PyLongObject; /* Revealed in longintrepr.h */ - PyAPI_DATA(PyTypeObject) PyLong_Type; #define PyLong_Check(op) \ @@ -26,9 +24,6 @@ PyAPI_FUNC(Py_ssize_t) PyLong_AsSsize_t(PyObject *); PyAPI_FUNC(size_t) PyLong_AsSize_t(PyObject *); PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLong(PyObject *); PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLongMask(PyObject *); -#ifndef Py_LIMITED_API -PyAPI_FUNC(int) _PyLong_AsInt(PyObject *); -#endif PyAPI_FUNC(PyObject *) PyLong_GetInfo(void); /* It may be useful in the future. I've added it in the PyInt -> PyLong @@ -65,30 +60,6 @@ PyAPI_FUNC(PyObject *) PyLong_GetInfo(void); # error "void* different in size from int, long and long long" #endif /* SIZEOF_VOID_P */ -#ifndef Py_LIMITED_API -PyAPI_FUNC(int) _PyLong_UnsignedShort_Converter(PyObject *, void *); -PyAPI_FUNC(int) _PyLong_UnsignedInt_Converter(PyObject *, void *); -PyAPI_FUNC(int) _PyLong_UnsignedLong_Converter(PyObject *, void *); -PyAPI_FUNC(int) _PyLong_UnsignedLongLong_Converter(PyObject *, void *); -PyAPI_FUNC(int) _PyLong_Size_t_Converter(PyObject *, void *); -#endif - -/* Used by Python/mystrtoul.c, _PyBytes_FromHex(), - _PyBytes_DecodeEscape(), etc. */ -#ifndef Py_LIMITED_API -PyAPI_DATA(unsigned char) _PyLong_DigitValue[256]; -#endif - -/* _PyLong_Frexp returns a double x and an exponent e such that the - true value is approximately equal to x * 2**e. e is >= 0. x is - 0.0 if and only if the input is 0 (in which case, e and x are both - zeroes); otherwise, 0.5 <= abs(x) < 1.0. On overflow, which is - possible if the number of bits doesn't fit into a Py_ssize_t, sets - OverflowError and returns -1.0 for x, 0 for e. */ -#ifndef Py_LIMITED_API -PyAPI_FUNC(double) _PyLong_Frexp(PyLongObject *a, Py_ssize_t *e); -#endif - PyAPI_FUNC(double) PyLong_AsDouble(PyObject *); PyAPI_FUNC(PyObject *) PyLong_FromVoidPtr(void *); PyAPI_FUNC(void *) PyLong_AsVoidPtr(PyObject *); @@ -101,102 +72,6 @@ PyAPI_FUNC(unsigned long long) PyLong_AsUnsignedLongLongMask(PyObject *); PyAPI_FUNC(long long) PyLong_AsLongLongAndOverflow(PyObject *, int *); PyAPI_FUNC(PyObject *) PyLong_FromString(const char *, char **, int); -#ifndef Py_LIMITED_API -PyAPI_FUNC(PyObject *) PyLong_FromUnicodeObject(PyObject *u, int base); -PyAPI_FUNC(PyObject *) _PyLong_FromBytes(const char *, Py_ssize_t, int); -#endif - -#ifndef Py_LIMITED_API -/* _PyLong_Sign. Return 0 if v is 0, -1 if v < 0, +1 if v > 0. - v must not be NULL, and must be a normalized long. - There are no error cases. -*/ -PyAPI_FUNC(int) _PyLong_Sign(PyObject *v); - - -/* _PyLong_NumBits. Return the number of bits needed to represent the - absolute value of a long. For example, this returns 1 for 1 and -1, 2 - for 2 and -2, and 2 for 3 and -3. It returns 0 for 0. - v must not be NULL, and must be a normalized long. - (size_t)-1 is returned and OverflowError set if the true result doesn't - fit in a size_t. -*/ -PyAPI_FUNC(size_t) _PyLong_NumBits(PyObject *v); - -/* _PyLong_DivmodNear. Given integers a and b, compute the nearest - integer q to the exact quotient a / b, rounding to the nearest even integer - in the case of a tie. Return (q, r), where r = a - q*b. The remainder r - will satisfy abs(r) <= abs(b)/2, with equality possible only if q is - even. -*/ -PyAPI_FUNC(PyObject *) _PyLong_DivmodNear(PyObject *, PyObject *); - -/* _PyLong_FromByteArray: View the n unsigned bytes as a binary integer in - base 256, and return a Python int with the same numeric value. - If n is 0, the integer is 0. Else: - If little_endian is 1/true, bytes[n-1] is the MSB and bytes[0] the LSB; - else (little_endian is 0/false) bytes[0] is the MSB and bytes[n-1] the - LSB. - If is_signed is 0/false, view the bytes as a non-negative integer. - If is_signed is 1/true, view the bytes as a 2's-complement integer, - non-negative if bit 0x80 of the MSB is clear, negative if set. - Error returns: - + Return NULL with the appropriate exception set if there's not - enough memory to create the Python int. -*/ -PyAPI_FUNC(PyObject *) _PyLong_FromByteArray( - const unsigned char* bytes, size_t n, - int little_endian, int is_signed); - -/* _PyLong_AsByteArray: Convert the least-significant 8*n bits of long - v to a base-256 integer, stored in array bytes. Normally return 0, - return -1 on error. - If little_endian is 1/true, store the MSB at bytes[n-1] and the LSB at - bytes[0]; else (little_endian is 0/false) store the MSB at bytes[0] and - the LSB at bytes[n-1]. - If is_signed is 0/false, it's an error if v < 0; else (v >= 0) n bytes - are filled and there's nothing special about bit 0x80 of the MSB. - If is_signed is 1/true, bytes is filled with the 2's-complement - representation of v's value. Bit 0x80 of the MSB is the sign bit. - Error returns (-1): - + is_signed is 0 and v < 0. TypeError is set in this case, and bytes - isn't altered. - + n isn't big enough to hold the full mathematical value of v. For - example, if is_signed is 0 and there are more digits in the v than - fit in n; or if is_signed is 1, v < 0, and n is just 1 bit shy of - being large enough to hold a sign bit. OverflowError is set in this - case, but bytes holds the least-significant n bytes of the true value. -*/ -PyAPI_FUNC(int) _PyLong_AsByteArray(PyLongObject* v, - unsigned char* bytes, size_t n, - int little_endian, int is_signed); - -/* _PyLong_Format: Convert the long to a string object with given base, - appending a base prefix of 0[box] if base is 2, 8 or 16. */ -PyAPI_FUNC(PyObject *) _PyLong_Format(PyObject *obj, int base); - -PyAPI_FUNC(int) _PyLong_FormatWriter( - _PyUnicodeWriter *writer, - PyObject *obj, - int base, - int alternate); - -PyAPI_FUNC(char*) _PyLong_FormatBytesWriter( - _PyBytesWriter *writer, - char *str, - PyObject *obj, - int base, - int alternate); - -/* Format the object based on the format_spec, as defined in PEP 3101 - (Advanced String Formatting). */ -PyAPI_FUNC(int) _PyLong_FormatAdvancedWriter( - _PyUnicodeWriter *writer, - PyObject *obj, - PyObject *format_spec, - Py_ssize_t start, - Py_ssize_t end); -#endif /* Py_LIMITED_API */ /* These aren't really part of the int object, but they're handy. The functions are in Python/mystrtoul.c. @@ -205,13 +80,9 @@ PyAPI_FUNC(unsigned long) PyOS_strtoul(const char *, char **, int); PyAPI_FUNC(long) PyOS_strtol(const char *, char **, int); #ifndef Py_LIMITED_API -/* For use by the gcd function in mathmodule.c */ -PyAPI_FUNC(PyObject *) _PyLong_GCD(PyObject *, PyObject *); -#endif /* !Py_LIMITED_API */ - -#ifndef Py_LIMITED_API -PyAPI_FUNC(PyObject *) _PyLong_Rshift(PyObject *, size_t); -PyAPI_FUNC(PyObject *) _PyLong_Lshift(PyObject *, size_t); +# define Py_CPYTHON_LONGOBJECT_H +# include "cpython/longobject.h" +# undef Py_CPYTHON_LONGOBJECT_H #endif #ifdef __cplusplus diff --git a/include/marshal.h b/include/marshal.h index 09d9337e..f8b0de80 100644 --- a/include/marshal.h +++ b/include/marshal.h @@ -3,26 +3,29 @@ #ifndef Py_MARSHAL_H #define Py_MARSHAL_H +#ifndef Py_LIMITED_API + #ifdef __cplusplus extern "C" { #endif -#define Py_MARSHAL_VERSION 4 - -PyAPI_FUNC(void) PyMarshal_WriteLongToFile(long, FILE *, int); -PyAPI_FUNC(void) PyMarshal_WriteObjectToFile(PyObject *, FILE *, int); +PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(const char *, + Py_ssize_t); PyAPI_FUNC(PyObject *) PyMarshal_WriteObjectToString(PyObject *, int); -#ifndef Py_LIMITED_API +#define Py_MARSHAL_VERSION 4 + PyAPI_FUNC(long) PyMarshal_ReadLongFromFile(FILE *); PyAPI_FUNC(int) PyMarshal_ReadShortFromFile(FILE *); PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromFile(FILE *); PyAPI_FUNC(PyObject *) PyMarshal_ReadLastObjectFromFile(FILE *); -#endif -PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(const char *, - Py_ssize_t); + +PyAPI_FUNC(void) PyMarshal_WriteLongToFile(long, FILE *, int); +PyAPI_FUNC(void) PyMarshal_WriteObjectToFile(PyObject *, FILE *, int); #ifdef __cplusplus } #endif + +#endif /* Py_LIMITED_API */ #endif /* !Py_MARSHAL_H */ diff --git a/include/memoryobject.h b/include/memoryobject.h index 306028f4..154397ce 100644 --- a/include/memoryobject.h +++ b/include/memoryobject.h @@ -25,8 +25,8 @@ PyAPI_FUNC(PyObject *) PyMemoryView_FromObject(PyObject *base); PyAPI_FUNC(PyObject *) PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags); #endif -#ifndef Py_LIMITED_API -PyAPI_FUNC(PyObject *) PyMemoryView_FromBuffer(Py_buffer *info); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030b0000 +PyAPI_FUNC(PyObject *) PyMemoryView_FromBuffer(const Py_buffer *info); #endif PyAPI_FUNC(PyObject *) PyMemoryView_GetContiguous(PyObject *base, int buffertype, diff --git a/include/methodobject.h b/include/methodobject.h index 9ffe8e1a..c971d78a 100644 --- a/include/methodobject.h +++ b/include/methodobject.h @@ -26,6 +26,25 @@ typedef PyObject *(*_PyCFunctionFastWithKeywords) (PyObject *, typedef PyObject *(*PyCMethod)(PyObject *, PyTypeObject *, PyObject *const *, size_t, PyObject *); +// Cast an function to the PyCFunction type to use it with PyMethodDef. +// +// This macro can be used to prevent compiler warnings if the first parameter +// uses a different pointer type than PyObject* (ex: METH_VARARGS and METH_O +// calling conventions). +// +// The macro can also be used for METH_FASTCALL and METH_VARARGS|METH_KEYWORDS +// calling conventions to avoid compiler warnings because the function has more +// than 2 parameters. The macro first casts the function to the +// "void func(void)" type to prevent compiler warnings. +// +// If a function is declared with the METH_NOARGS calling convention, it must +// have 2 parameters. Since the second parameter is unused, Py_UNUSED() can be +// used to prevent a compiler warning. If the function has a single parameter, +// it triggers an undefined behavior when Python calls it with 2 parameters +// (bpo-33012). +#define _PyCFunction_CAST(func) \ + _Py_CAST(PyCFunction, _Py_CAST(void(*)(void), (func))) + PyAPI_FUNC(PyCFunction) PyCFunction_GetFunction(PyObject *); PyAPI_FUNC(PyObject *) PyCFunction_GetSelf(PyObject *); PyAPI_FUNC(int) PyCFunction_GetFlags(PyObject *); @@ -39,7 +58,6 @@ struct PyMethodDef { describe the args expected by the C func */ const char *ml_doc; /* The __doc__ attribute, or NULL */ }; -typedef struct PyMethodDef PyMethodDef; /* PyCFunction_New is declared as a function for stable ABI (declaration is * needed for e.g. GCC with -fvisibility=hidden), but redefined as a macro @@ -103,11 +121,9 @@ PyAPI_FUNC(PyObject *) PyCMethod_New(PyMethodDef *, PyObject *, #ifndef Py_LIMITED_API - -#define Py_CPYTHON_METHODOBJECT_H -#include "cpython/methodobject.h" -#undef Py_CPYTHON_METHODOBJECT_H - +# define Py_CPYTHON_METHODOBJECT_H +# include "cpython/methodobject.h" +# undef Py_CPYTHON_METHODOBJECT_H #endif #ifdef __cplusplus diff --git a/include/modsupport.h b/include/modsupport.h index f009d586..0e96a5c9 100644 --- a/include/modsupport.h +++ b/include/modsupport.h @@ -7,7 +7,7 @@ extern "C" { /* Module support interface */ -#include +#include // va_list /* If PY_SSIZE_T_CLEAN is defined, each functions treats #-specifier to mean Py_ssize_t */ @@ -19,19 +19,6 @@ extern "C" { #define PyArg_VaParseTupleAndKeywords _PyArg_VaParseTupleAndKeywords_SizeT #define Py_BuildValue _Py_BuildValue_SizeT #define Py_VaBuildValue _Py_VaBuildValue_SizeT -#ifndef Py_LIMITED_API -#define _Py_VaBuildStack _Py_VaBuildStack_SizeT -#endif -#else -#ifndef Py_LIMITED_API -PyAPI_FUNC(PyObject *) _Py_VaBuildValue_SizeT(const char *, va_list); -PyAPI_FUNC(PyObject **) _Py_VaBuildStack_SizeT( - PyObject **small_stack, - Py_ssize_t small_stack_len, - const char *format, - va_list va, - Py_ssize_t *p_nargs); -#endif /* !Py_LIMITED_API */ #endif /* Due to a glitch in 3.2, the _SizeT versions weren't exported from the DLL. */ @@ -50,91 +37,9 @@ PyAPI_FUNC(PyObject *) Py_BuildValue(const char *, ...); PyAPI_FUNC(PyObject *) _Py_BuildValue_SizeT(const char *, ...); -#ifndef Py_LIMITED_API -PyAPI_FUNC(int) _PyArg_UnpackStack( - PyObject *const *args, - Py_ssize_t nargs, - const char *name, - Py_ssize_t min, - Py_ssize_t max, - ...); - -PyAPI_FUNC(int) _PyArg_NoKeywords(const char *funcname, PyObject *kwargs); -PyAPI_FUNC(int) _PyArg_NoKwnames(const char *funcname, PyObject *kwnames); -PyAPI_FUNC(int) _PyArg_NoPositional(const char *funcname, PyObject *args); -#define _PyArg_NoKeywords(funcname, kwargs) \ - ((kwargs) == NULL || _PyArg_NoKeywords((funcname), (kwargs))) -#define _PyArg_NoKwnames(funcname, kwnames) \ - ((kwnames) == NULL || _PyArg_NoKwnames((funcname), (kwnames))) -#define _PyArg_NoPositional(funcname, args) \ - ((args) == NULL || _PyArg_NoPositional((funcname), (args))) - -PyAPI_FUNC(void) _PyArg_BadArgument(const char *, const char *, const char *, PyObject *); -PyAPI_FUNC(int) _PyArg_CheckPositional(const char *, Py_ssize_t, - Py_ssize_t, Py_ssize_t); -#define _PyArg_CheckPositional(funcname, nargs, min, max) \ - (((min) <= (nargs) && (nargs) <= (max)) \ - || _PyArg_CheckPositional((funcname), (nargs), (min), (max))) - -#endif +#define ANY_VARARGS(n) (n == PY_SSIZE_T_MAX) PyAPI_FUNC(PyObject *) Py_VaBuildValue(const char *, va_list); -#ifndef Py_LIMITED_API -PyAPI_FUNC(PyObject **) _Py_VaBuildStack( - PyObject **small_stack, - Py_ssize_t small_stack_len, - const char *format, - va_list va, - Py_ssize_t *p_nargs); -#endif - -#ifndef Py_LIMITED_API -typedef struct _PyArg_Parser { - const char *format; - const char * const *keywords; - const char *fname; - const char *custom_msg; - int pos; /* number of positional-only arguments */ - int min; /* minimal number of arguments */ - int max; /* maximal number of positional arguments */ - PyObject *kwtuple; /* tuple of keyword parameter names */ - struct _PyArg_Parser *next; -} _PyArg_Parser; -#ifdef PY_SSIZE_T_CLEAN -#define _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT -#define _PyArg_ParseStack _PyArg_ParseStack_SizeT -#define _PyArg_ParseStackAndKeywords _PyArg_ParseStackAndKeywords_SizeT -#define _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT -#endif -PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *, - struct _PyArg_Parser *, ...); -PyAPI_FUNC(int) _PyArg_ParseStack( - PyObject *const *args, - Py_ssize_t nargs, - const char *format, - ...); -PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords( - PyObject *const *args, - Py_ssize_t nargs, - PyObject *kwnames, - struct _PyArg_Parser *, - ...); -PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *, - struct _PyArg_Parser *, va_list); -PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywords( - PyObject *const *args, Py_ssize_t nargs, - PyObject *kwargs, PyObject *kwnames, - struct _PyArg_Parser *parser, - int minpos, int maxpos, int minkw, - PyObject **buf); -#define _PyArg_UnpackKeywords(args, nargs, kwargs, kwnames, parser, minpos, maxpos, minkw, buf) \ - (((minkw) == 0 && (kwargs) == NULL && (kwnames) == NULL && \ - (minpos) <= (nargs) && (nargs) <= (maxpos) && args != NULL) ? (args) : \ - _PyArg_UnpackKeywords((args), (nargs), (kwargs), (kwnames), (parser), \ - (minpos), (maxpos), (minkw), (buf))) - -void _PyArg_Fini(void); -#endif /* Py_LIMITED_API */ // Add an attribute with name 'name' and value 'obj' to the module 'mod. // On success, return 0 on success. @@ -147,10 +52,12 @@ PyAPI_FUNC(int) PyModule_AddObject(PyObject *mod, const char *, PyObject *value) PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *, const char *, long); PyAPI_FUNC(int) PyModule_AddStringConstant(PyObject *, const char *, const char *); + #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03090000 /* New in 3.9 */ PyAPI_FUNC(int) PyModule_AddType(PyObject *module, PyTypeObject *type); #endif /* Py_LIMITED_API */ + #define PyModule_AddIntMacro(m, c) PyModule_AddIntConstant(m, #c, c) #define PyModule_AddStringMacro(m, c) PyModule_AddStringConstant(m, #c, c) @@ -223,12 +130,7 @@ PyAPI_FUNC(int) PyModule_ExecDef(PyObject *module, PyModuleDef *def); #define PyModule_FromDefAndSpec2 PyModule_FromDefAndSpec2TraceRefs #endif -PyAPI_FUNC(PyObject *) PyModule_Create2(struct PyModuleDef*, - int apiver); -#ifndef Py_LIMITED_API -PyAPI_FUNC(PyObject *) _PyModule_CreateInitialized(struct PyModuleDef*, - int apiver); -#endif +PyAPI_FUNC(PyObject *) PyModule_Create2(PyModuleDef*, int apiver); #ifdef Py_LIMITED_API #define PyModule_Create(module) \ @@ -251,10 +153,13 @@ PyAPI_FUNC(PyObject *) PyModule_FromDefAndSpec2(PyModuleDef *def, #define PyModule_FromDefAndSpec(module, spec) \ PyModule_FromDefAndSpec2(module, spec, PYTHON_API_VERSION) #endif /* Py_LIMITED_API */ + #endif /* New in 3.5 */ #ifndef Py_LIMITED_API -PyAPI_DATA(const char *) _Py_PackageContext; +# define Py_CPYTHON_MODSUPPORT_H +# include "cpython/modsupport.h" +# undef Py_CPYTHON_MODSUPPORT_H #endif #ifdef __cplusplus diff --git a/include/moduleobject.h b/include/moduleobject.h index 49b116ca..75abd2cf 100644 --- a/include/moduleobject.h +++ b/include/moduleobject.h @@ -32,12 +32,12 @@ PyAPI_FUNC(void) _PyModule_Clear(PyObject *); PyAPI_FUNC(void) _PyModule_ClearDict(PyObject *); PyAPI_FUNC(int) _PyModuleSpec_IsInitializing(PyObject *); #endif -PyAPI_FUNC(struct PyModuleDef*) PyModule_GetDef(PyObject*); +PyAPI_FUNC(PyModuleDef*) PyModule_GetDef(PyObject*); PyAPI_FUNC(void*) PyModule_GetState(PyObject*); #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 /* New in 3.5 */ -PyAPI_FUNC(PyObject *) PyModuleDef_Init(struct PyModuleDef*); +PyAPI_FUNC(PyObject *) PyModuleDef_Init(PyModuleDef*); PyAPI_DATA(PyTypeObject) PyModuleDef_Type; #endif @@ -48,20 +48,19 @@ typedef struct PyModuleDef_Base { PyObject* m_copy; } PyModuleDef_Base; -#define PyModuleDef_HEAD_INIT { \ - PyObject_HEAD_INIT(NULL) \ - NULL, /* m_init */ \ - 0, /* m_index */ \ - NULL, /* m_copy */ \ +#define PyModuleDef_HEAD_INIT { \ + PyObject_HEAD_INIT(_Py_NULL) \ + _Py_NULL, /* m_init */ \ + 0, /* m_index */ \ + _Py_NULL, /* m_copy */ \ } -struct PyModuleDef_Slot; #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 /* New in 3.5 */ -typedef struct PyModuleDef_Slot{ +struct PyModuleDef_Slot { int slot; void *value; -} PyModuleDef_Slot; +}; #define Py_mod_create 1 #define Py_mod_exec 2 @@ -72,17 +71,17 @@ typedef struct PyModuleDef_Slot{ #endif /* New in 3.5 */ -typedef struct PyModuleDef{ +struct PyModuleDef { PyModuleDef_Base m_base; const char* m_name; const char* m_doc; Py_ssize_t m_size; PyMethodDef *m_methods; - struct PyModuleDef_Slot* m_slots; + PyModuleDef_Slot *m_slots; traverseproc m_traverse; inquiry m_clear; freefunc m_free; -} PyModuleDef; +}; // Internal C API diff --git a/include/namespaceobject.h b/include/namespaceobject.h deleted file mode 100644 index 0c8d95c0..00000000 --- a/include/namespaceobject.h +++ /dev/null @@ -1,19 +0,0 @@ - -/* simple namespace object interface */ - -#ifndef NAMESPACEOBJECT_H -#define NAMESPACEOBJECT_H -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef Py_LIMITED_API -PyAPI_DATA(PyTypeObject) _PyNamespace_Type; - -PyAPI_FUNC(PyObject *) _PyNamespace_New(PyObject *kwds); -#endif /* !Py_LIMITED_API */ - -#ifdef __cplusplus -} -#endif -#endif /* !NAMESPACEOBJECT_H */ diff --git a/include/object.h b/include/object.h index 61e638c3..f2af428e 100644 --- a/include/object.h +++ b/include/object.h @@ -1,6 +1,5 @@ #ifndef Py_OBJECT_H #define Py_OBJECT_H - #ifdef __cplusplus extern "C" { #endif @@ -61,17 +60,13 @@ whose size is determined when the object is allocated. # error Py_LIMITED_API is incompatible with Py_TRACE_REFS #endif -/* PyTypeObject structure is defined in cpython/object.h. - In Py_LIMITED_API, PyTypeObject is an opaque structure. */ -typedef struct _typeobject PyTypeObject; - #ifdef Py_TRACE_REFS /* Define pointers to support a doubly-linked list of all live heap objects. */ #define _PyObject_HEAD_EXTRA \ - struct _object *_ob_next; \ - struct _object *_ob_prev; + PyObject *_ob_next; \ + PyObject *_ob_prev; -#define _PyObject_EXTRA_INIT 0, 0, +#define _PyObject_EXTRA_INIT _Py_NULL, _Py_NULL, #else # define _PyObject_HEAD_EXTRA @@ -102,15 +97,14 @@ typedef struct _typeobject PyTypeObject; * by hand. Similarly every pointer to a variable-size Python object can, * in addition, be cast to PyVarObject*. */ -typedef struct _object { +struct _object { _PyObject_HEAD_EXTRA Py_ssize_t ob_refcnt; PyTypeObject *ob_type; -} PyObject; +}; /* Cast argument to PyObject* type. */ -#define _PyObject_CAST(op) ((PyObject*)(op)) -#define _PyObject_CAST_CONST(op) ((const PyObject*)(op)) +#define _PyObject_CAST(op) _Py_CAST(PyObject*, (op)) typedef struct { PyObject ob_base; @@ -118,8 +112,7 @@ typedef struct { } PyVarObject; /* Cast argument to PyVarObject* type. */ -#define _PyVarObject_CAST(op) ((PyVarObject*)(op)) -#define _PyVarObject_CAST_CONST(op) ((const PyVarObject*)(op)) +#define _PyVarObject_CAST(op) _Py_CAST(PyVarObject*, (op)) // Test if the 'x' object is the 'y' object, the same as "x is y" in Python. @@ -127,43 +120,62 @@ PyAPI_FUNC(int) Py_Is(PyObject *x, PyObject *y); #define Py_Is(x, y) ((x) == (y)) -static inline Py_ssize_t _Py_REFCNT(const PyObject *ob) { +static inline Py_ssize_t Py_REFCNT(PyObject *ob) { return ob->ob_refcnt; } -#define Py_REFCNT(ob) _Py_REFCNT(_PyObject_CAST_CONST(ob)) +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define Py_REFCNT(ob) Py_REFCNT(_PyObject_CAST(ob)) +#endif // bpo-39573: The Py_SET_TYPE() function must be used to set an object type. -#define Py_TYPE(ob) (_PyObject_CAST(ob)->ob_type) +static inline PyTypeObject* Py_TYPE(PyObject *ob) { + return ob->ob_type; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define Py_TYPE(ob) Py_TYPE(_PyObject_CAST(ob)) +#endif // bpo-39573: The Py_SET_SIZE() function must be used to set an object size. -#define Py_SIZE(ob) (_PyVarObject_CAST(ob)->ob_size) +static inline Py_ssize_t Py_SIZE(PyObject *ob) { + PyVarObject *var_ob = _PyVarObject_CAST(ob); + return var_ob->ob_size; +} +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define Py_SIZE(ob) Py_SIZE(_PyObject_CAST(ob)) +#endif -static inline int _Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) { - // bpo-44378: Don't use Py_TYPE() since Py_TYPE() requires a non-const - // object. - return ob->ob_type == type; +static inline int Py_IS_TYPE(PyObject *ob, PyTypeObject *type) { + return Py_TYPE(ob) == type; } -#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST_CONST(ob), type) +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define Py_IS_TYPE(ob, type) Py_IS_TYPE(_PyObject_CAST(ob), type) +#endif -static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { +static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { ob->ob_refcnt = refcnt; } -#define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt) +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define Py_SET_REFCNT(ob, refcnt) Py_SET_REFCNT(_PyObject_CAST(ob), refcnt) +#endif -static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) { +static inline void Py_SET_TYPE(PyObject *ob, PyTypeObject *type) { ob->ob_type = type; } -#define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type) +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define Py_SET_TYPE(ob, type) Py_SET_TYPE(_PyObject_CAST(ob), type) +#endif -static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) { +static inline void Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) { ob->ob_size = size; } -#define Py_SET_SIZE(ob, size) _Py_SET_SIZE(_PyVarObject_CAST(ob), size) +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define Py_SET_SIZE(ob, size) Py_SET_SIZE(_PyVarObject_CAST(ob), size) +#endif /* @@ -236,17 +248,23 @@ PyAPI_FUNC(void*) PyType_GetSlot(PyTypeObject*, int); #endif #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03090000 PyAPI_FUNC(PyObject*) PyType_FromModuleAndSpec(PyObject *, PyType_Spec *, PyObject *); -PyAPI_FUNC(PyObject *) PyType_GetModule(struct _typeobject *); -PyAPI_FUNC(void *) PyType_GetModuleState(struct _typeobject *); +PyAPI_FUNC(PyObject *) PyType_GetModule(PyTypeObject *); +PyAPI_FUNC(void *) PyType_GetModuleState(PyTypeObject *); +#endif +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030B0000 +PyAPI_FUNC(PyObject *) PyType_GetName(PyTypeObject *); +PyAPI_FUNC(PyObject *) PyType_GetQualName(PyTypeObject *); #endif /* Generic type check */ PyAPI_FUNC(int) PyType_IsSubtype(PyTypeObject *, PyTypeObject *); -static inline int _PyObject_TypeCheck(PyObject *ob, PyTypeObject *type) { +static inline int PyObject_TypeCheck(PyObject *ob, PyTypeObject *type) { return Py_IS_TYPE(ob, type) || PyType_IsSubtype(Py_TYPE(ob), type); } -#define PyObject_TypeCheck(ob, type) _PyObject_TypeCheck(_PyObject_CAST(ob), type) +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyObject_TypeCheck(ob, type) PyObject_TypeCheck(_PyObject_CAST(ob), type) +#endif PyAPI_DATA(PyTypeObject) PyType_Type; /* built-in 'type' */ PyAPI_DATA(PyTypeObject) PyBaseObject_Type; /* built-in 'object' */ @@ -294,6 +312,11 @@ PyAPI_FUNC(void) PyObject_ClearWeakRefs(PyObject *); */ PyAPI_FUNC(PyObject *) PyObject_Dir(PyObject *); +/* Pickle support. */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyObject_GetState(PyObject *); +#endif + /* Helpers for printing recursive container types */ PyAPI_FUNC(int) Py_ReprEnter(PyObject *); @@ -323,6 +346,13 @@ given type object has a specified feature. */ #ifndef Py_LIMITED_API + +/* Placement of dict (and values) pointers are managed by the VM, not by the type. + * The VM will automatically set tp_dictoffset. Should not be used for variable sized + * classes, such as classes that extend tuple. + */ +#define Py_TPFLAGS_MANAGED_DICT (1 << 4) + /* Set if instances of the type object are treated as sequences for pattern matching */ #define Py_TPFLAGS_SEQUENCE (1 << 5) /* Set if instances of the type object are treated as mappings for pattern matching */ @@ -458,7 +488,7 @@ PyAPI_FUNC(void) Py_DecRef(PyObject *); PyAPI_FUNC(void) _Py_IncRef(PyObject *); PyAPI_FUNC(void) _Py_DecRef(PyObject *); -static inline void _Py_INCREF(PyObject *op) +static inline void Py_INCREF(PyObject *op) { #if defined(Py_REF_DEBUG) && defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030A0000 // Stable ABI for Python 3.10 built in debug mode. @@ -472,39 +502,43 @@ static inline void _Py_INCREF(PyObject *op) op->ob_refcnt++; #endif } -#define Py_INCREF(op) _Py_INCREF(_PyObject_CAST(op)) - -static inline void _Py_DECREF( -#if defined(Py_REF_DEBUG) && !(defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030A0000) - const char *filename, int lineno, +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define Py_INCREF(op) Py_INCREF(_PyObject_CAST(op)) #endif - PyObject *op) -{ + + #if defined(Py_REF_DEBUG) && defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030A0000 - // Stable ABI for Python 3.10 built in debug mode. +// Stable ABI for limited C API version 3.10 of Python debug build +static inline void Py_DECREF(PyObject *op) { _Py_DecRef(op); -#else - // Non-limited C API and limited C API for Python 3.9 and older access - // directly PyObject.ob_refcnt. -#ifdef Py_REF_DEBUG +} +#define Py_DECREF(op) Py_DECREF(_PyObject_CAST(op)) + +#elif defined(Py_REF_DEBUG) +static inline void Py_DECREF(const char *filename, int lineno, PyObject *op) +{ _Py_RefTotal--; -#endif if (--op->ob_refcnt != 0) { -#ifdef Py_REF_DEBUG if (op->ob_refcnt < 0) { _Py_NegativeRefcount(filename, lineno, op); } -#endif } else { _Py_Dealloc(op); } -#endif } -#if defined(Py_REF_DEBUG) && !(defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030A0000) -# define Py_DECREF(op) _Py_DECREF(__FILE__, __LINE__, _PyObject_CAST(op)) +#define Py_DECREF(op) Py_DECREF(__FILE__, __LINE__, _PyObject_CAST(op)) + #else -# define Py_DECREF(op) _Py_DECREF(_PyObject_CAST(op)) +static inline void Py_DECREF(PyObject *op) +{ + // Non-limited C API and limited C API for Python 3.9 and older access + // directly PyObject.ob_refcnt. + if (--op->ob_refcnt == 0) { + _Py_Dealloc(op); + } +} +#define Py_DECREF(op) Py_DECREF(_PyObject_CAST(op)) #endif @@ -552,23 +586,25 @@ static inline void _Py_DECREF( } while (0) /* Function to use in case the object pointer can be NULL: */ -static inline void _Py_XINCREF(PyObject *op) +static inline void Py_XINCREF(PyObject *op) { - if (op != NULL) { + if (op != _Py_NULL) { Py_INCREF(op); } } +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define Py_XINCREF(op) Py_XINCREF(_PyObject_CAST(op)) +#endif -#define Py_XINCREF(op) _Py_XINCREF(_PyObject_CAST(op)) - -static inline void _Py_XDECREF(PyObject *op) +static inline void Py_XDECREF(PyObject *op) { - if (op != NULL) { + if (op != _Py_NULL) { Py_DECREF(op); } } - -#define Py_XDECREF(op) _Py_XDECREF(_PyObject_CAST(op)) +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define Py_XDECREF(op) Py_XDECREF(_PyObject_CAST(op)) +#endif // Create a new strong reference to an object: // increment the reference count of the object and return the object. @@ -592,8 +628,13 @@ static inline PyObject* _Py_XNewRef(PyObject *obj) // Py_NewRef() and Py_XNewRef() are exported as functions for the stable ABI. // Names overridden with macros by static inline functions for best // performances. -#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj)) -#define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj)) +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj)) +# define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj)) +#else +# define Py_NewRef(obj) _Py_NewRef(obj) +# define Py_XNewRef(obj) _Py_XNewRef(obj) +#endif /* @@ -713,7 +754,7 @@ times. #ifndef Py_LIMITED_API # define Py_CPYTHON_OBJECT_H -# include "cpython/object.h" +# include "cpython/object.h" # undef Py_CPYTHON_OBJECT_H #endif @@ -733,17 +774,24 @@ PyType_HasFeature(PyTypeObject *type, unsigned long feature) #define PyType_FastSubclass(type, flag) PyType_HasFeature(type, flag) -static inline int _PyType_Check(PyObject *op) { +static inline int PyType_Check(PyObject *op) { return PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TYPE_SUBCLASS); } -#define PyType_Check(op) _PyType_Check(_PyObject_CAST(op)) +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyType_Check(op) PyType_Check(_PyObject_CAST(op)) +#endif + +#define _PyType_CAST(op) \ + (assert(PyType_Check(op)), _Py_CAST(PyTypeObject*, (op))) -static inline int _PyType_CheckExact(PyObject *op) { +static inline int PyType_CheckExact(PyObject *op) { return Py_IS_TYPE(op, &PyType_Type); } -#define PyType_CheckExact(op) _PyType_CheckExact(_PyObject_CAST(op)) +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define PyType_CheckExact(op) PyType_CheckExact(_PyObject_CAST(op)) +#endif #ifdef __cplusplus } #endif -#endif /* !Py_OBJECT_H */ +#endif // !Py_OBJECT_H diff --git a/include/objimpl.h b/include/objimpl.h index 450befad..4fa670e7 100644 --- a/include/objimpl.h +++ b/include/objimpl.h @@ -182,9 +182,9 @@ PyAPI_FUNC(void) PyObject_GC_UnTrack(void *); PyAPI_FUNC(void) PyObject_GC_Del(void *); #define PyObject_GC_New(type, typeobj) \ - ( (type *) _PyObject_GC_New(typeobj) ) + _Py_CAST(type*, _PyObject_GC_New(typeobj)) #define PyObject_GC_NewVar(type, typeobj, n) \ - ( (type *) _PyObject_GC_NewVar((typeobj), (n)) ) + _Py_CAST(type*, _PyObject_GC_NewVar((typeobj), (n))) PyAPI_FUNC(int) PyObject_GC_IsTracked(PyObject *); PyAPI_FUNC(int) PyObject_GC_IsFinalized(PyObject *); @@ -205,7 +205,7 @@ PyAPI_FUNC(int) PyObject_GC_IsFinalized(PyObject *); #ifndef Py_LIMITED_API # define Py_CPYTHON_OBJIMPL_H -# include "cpython/objimpl.h" +# include "cpython/objimpl.h" # undef Py_CPYTHON_OBJIMPL_H #endif diff --git a/include/opcode.h b/include/opcode.h index 52039754..084d34b8 100644 --- a/include/opcode.h +++ b/include/opcode.h @@ -1,4 +1,5 @@ -/* Auto-generated by Tools/scripts/generate_opcode_h.py from Lib/opcode.py */ +// Auto-generated by Tools/scripts/generate_opcode_h.py from Lib/opcode.py + #ifndef Py_OPCODE_H #define Py_OPCODE_H #ifdef __cplusplus @@ -6,166 +7,229 @@ extern "C" { #endif - /* Instruction opcodes for compiled code */ -#define POP_TOP 1 -#define ROT_TWO 2 -#define ROT_THREE 3 -#define DUP_TOP 4 -#define DUP_TOP_TWO 5 -#define ROT_FOUR 6 -#define NOP 9 -#define UNARY_POSITIVE 10 -#define UNARY_NEGATIVE 11 -#define UNARY_NOT 12 -#define UNARY_INVERT 15 -#define BINARY_MATRIX_MULTIPLY 16 -#define INPLACE_MATRIX_MULTIPLY 17 -#define BINARY_POWER 19 -#define BINARY_MULTIPLY 20 -#define BINARY_MODULO 22 -#define BINARY_ADD 23 -#define BINARY_SUBTRACT 24 -#define BINARY_SUBSCR 25 -#define BINARY_FLOOR_DIVIDE 26 -#define BINARY_TRUE_DIVIDE 27 -#define INPLACE_FLOOR_DIVIDE 28 -#define INPLACE_TRUE_DIVIDE 29 -#define GET_LEN 30 -#define MATCH_MAPPING 31 -#define MATCH_SEQUENCE 32 -#define MATCH_KEYS 33 -#define COPY_DICT_WITHOUT_KEYS 34 -#define WITH_EXCEPT_START 49 -#define GET_AITER 50 -#define GET_ANEXT 51 -#define BEFORE_ASYNC_WITH 52 -#define END_ASYNC_FOR 54 -#define INPLACE_ADD 55 -#define INPLACE_SUBTRACT 56 -#define INPLACE_MULTIPLY 57 -#define INPLACE_MODULO 59 -#define STORE_SUBSCR 60 -#define DELETE_SUBSCR 61 -#define BINARY_LSHIFT 62 -#define BINARY_RSHIFT 63 -#define BINARY_AND 64 -#define BINARY_XOR 65 -#define BINARY_OR 66 -#define INPLACE_POWER 67 -#define GET_ITER 68 -#define GET_YIELD_FROM_ITER 69 -#define PRINT_EXPR 70 -#define LOAD_BUILD_CLASS 71 -#define YIELD_FROM 72 -#define GET_AWAITABLE 73 -#define LOAD_ASSERTION_ERROR 74 -#define INPLACE_LSHIFT 75 -#define INPLACE_RSHIFT 76 -#define INPLACE_AND 77 -#define INPLACE_XOR 78 -#define INPLACE_OR 79 -#define LIST_TO_TUPLE 82 -#define RETURN_VALUE 83 -#define IMPORT_STAR 84 -#define SETUP_ANNOTATIONS 85 -#define YIELD_VALUE 86 -#define POP_BLOCK 87 -#define POP_EXCEPT 89 -#define HAVE_ARGUMENT 90 -#define STORE_NAME 90 -#define DELETE_NAME 91 -#define UNPACK_SEQUENCE 92 -#define FOR_ITER 93 -#define UNPACK_EX 94 -#define STORE_ATTR 95 -#define DELETE_ATTR 96 -#define STORE_GLOBAL 97 -#define DELETE_GLOBAL 98 -#define ROT_N 99 -#define LOAD_CONST 100 -#define LOAD_NAME 101 -#define BUILD_TUPLE 102 -#define BUILD_LIST 103 -#define BUILD_SET 104 -#define BUILD_MAP 105 -#define LOAD_ATTR 106 -#define COMPARE_OP 107 -#define IMPORT_NAME 108 -#define IMPORT_FROM 109 -#define JUMP_FORWARD 110 -#define JUMP_IF_FALSE_OR_POP 111 -#define JUMP_IF_TRUE_OR_POP 112 -#define JUMP_ABSOLUTE 113 -#define POP_JUMP_IF_FALSE 114 -#define POP_JUMP_IF_TRUE 115 -#define LOAD_GLOBAL 116 -#define IS_OP 117 -#define CONTAINS_OP 118 -#define RERAISE 119 -#define JUMP_IF_NOT_EXC_MATCH 121 -#define SETUP_FINALLY 122 -#define LOAD_FAST 124 -#define STORE_FAST 125 -#define DELETE_FAST 126 -#define GEN_START 129 -#define RAISE_VARARGS 130 -#define CALL_FUNCTION 131 -#define MAKE_FUNCTION 132 -#define BUILD_SLICE 133 -#define LOAD_CLOSURE 135 -#define LOAD_DEREF 136 -#define STORE_DEREF 137 -#define DELETE_DEREF 138 -#define CALL_FUNCTION_KW 141 -#define CALL_FUNCTION_EX 142 -#define SETUP_WITH 143 -#define EXTENDED_ARG 144 -#define LIST_APPEND 145 -#define SET_ADD 146 -#define MAP_ADD 147 -#define LOAD_CLASSDEREF 148 -#define MATCH_CLASS 152 -#define SETUP_ASYNC_WITH 154 -#define FORMAT_VALUE 155 -#define BUILD_CONST_KEY_MAP 156 -#define BUILD_STRING 157 -#define LOAD_METHOD 160 -#define CALL_METHOD 161 -#define LIST_EXTEND 162 -#define SET_UPDATE 163 -#define DICT_MERGE 164 -#define DICT_UPDATE 165 -#ifdef NEED_OPCODE_JUMP_TABLES -static uint32_t _PyOpcode_RelativeJump[8] = { - 0U, - 0U, - 536870912U, - 67125248U, - 67141632U, - 0U, - 0U, - 0U, -}; -static uint32_t _PyOpcode_Jump[8] = { - 0U, - 0U, - 536870912U, - 101695488U, - 67141632U, - 0U, - 0U, - 0U, -}; -#endif /* OPCODE_TABLES */ +/* Instruction opcodes for compiled code */ +#define CACHE 0 +#define POP_TOP 1 +#define PUSH_NULL 2 +#define NOP 9 +#define UNARY_POSITIVE 10 +#define UNARY_NEGATIVE 11 +#define UNARY_NOT 12 +#define UNARY_INVERT 15 +#define BINARY_SUBSCR 25 +#define GET_LEN 30 +#define MATCH_MAPPING 31 +#define MATCH_SEQUENCE 32 +#define MATCH_KEYS 33 +#define PUSH_EXC_INFO 35 +#define CHECK_EXC_MATCH 36 +#define CHECK_EG_MATCH 37 +#define WITH_EXCEPT_START 49 +#define GET_AITER 50 +#define GET_ANEXT 51 +#define BEFORE_ASYNC_WITH 52 +#define BEFORE_WITH 53 +#define END_ASYNC_FOR 54 +#define STORE_SUBSCR 60 +#define DELETE_SUBSCR 61 +#define GET_ITER 68 +#define GET_YIELD_FROM_ITER 69 +#define PRINT_EXPR 70 +#define LOAD_BUILD_CLASS 71 +#define LOAD_ASSERTION_ERROR 74 +#define RETURN_GENERATOR 75 +#define LIST_TO_TUPLE 82 +#define RETURN_VALUE 83 +#define IMPORT_STAR 84 +#define SETUP_ANNOTATIONS 85 +#define YIELD_VALUE 86 +#define ASYNC_GEN_WRAP 87 +#define PREP_RERAISE_STAR 88 +#define POP_EXCEPT 89 +#define HAVE_ARGUMENT 90 +#define STORE_NAME 90 +#define DELETE_NAME 91 +#define UNPACK_SEQUENCE 92 +#define FOR_ITER 93 +#define UNPACK_EX 94 +#define STORE_ATTR 95 +#define DELETE_ATTR 96 +#define STORE_GLOBAL 97 +#define DELETE_GLOBAL 98 +#define SWAP 99 +#define LOAD_CONST 100 +#define LOAD_NAME 101 +#define BUILD_TUPLE 102 +#define BUILD_LIST 103 +#define BUILD_SET 104 +#define BUILD_MAP 105 +#define LOAD_ATTR 106 +#define COMPARE_OP 107 +#define IMPORT_NAME 108 +#define IMPORT_FROM 109 +#define JUMP_FORWARD 110 +#define JUMP_IF_FALSE_OR_POP 111 +#define JUMP_IF_TRUE_OR_POP 112 +#define POP_JUMP_FORWARD_IF_FALSE 114 +#define POP_JUMP_FORWARD_IF_TRUE 115 +#define LOAD_GLOBAL 116 +#define IS_OP 117 +#define CONTAINS_OP 118 +#define RERAISE 119 +#define COPY 120 +#define BINARY_OP 122 +#define SEND 123 +#define LOAD_FAST 124 +#define STORE_FAST 125 +#define DELETE_FAST 126 +#define POP_JUMP_FORWARD_IF_NOT_NONE 128 +#define POP_JUMP_FORWARD_IF_NONE 129 +#define RAISE_VARARGS 130 +#define GET_AWAITABLE 131 +#define MAKE_FUNCTION 132 +#define BUILD_SLICE 133 +#define JUMP_BACKWARD_NO_INTERRUPT 134 +#define MAKE_CELL 135 +#define LOAD_CLOSURE 136 +#define LOAD_DEREF 137 +#define STORE_DEREF 138 +#define DELETE_DEREF 139 +#define JUMP_BACKWARD 140 +#define CALL_FUNCTION_EX 142 +#define EXTENDED_ARG 144 +#define LIST_APPEND 145 +#define SET_ADD 146 +#define MAP_ADD 147 +#define LOAD_CLASSDEREF 148 +#define COPY_FREE_VARS 149 +#define RESUME 151 +#define MATCH_CLASS 152 +#define FORMAT_VALUE 155 +#define BUILD_CONST_KEY_MAP 156 +#define BUILD_STRING 157 +#define LOAD_METHOD 160 +#define LIST_EXTEND 162 +#define SET_UPDATE 163 +#define DICT_MERGE 164 +#define DICT_UPDATE 165 +#define PRECALL 166 +#define CALL 171 +#define KW_NAMES 172 +#define POP_JUMP_BACKWARD_IF_NOT_NONE 173 +#define POP_JUMP_BACKWARD_IF_NONE 174 +#define POP_JUMP_BACKWARD_IF_FALSE 175 +#define POP_JUMP_BACKWARD_IF_TRUE 176 +#define BINARY_OP_ADAPTIVE 3 +#define BINARY_OP_ADD_FLOAT 4 +#define BINARY_OP_ADD_INT 5 +#define BINARY_OP_ADD_UNICODE 6 +#define BINARY_OP_INPLACE_ADD_UNICODE 7 +#define BINARY_OP_MULTIPLY_FLOAT 8 +#define BINARY_OP_MULTIPLY_INT 13 +#define BINARY_OP_SUBTRACT_FLOAT 14 +#define BINARY_OP_SUBTRACT_INT 16 +#define BINARY_SUBSCR_ADAPTIVE 17 +#define BINARY_SUBSCR_DICT 18 +#define BINARY_SUBSCR_GETITEM 19 +#define BINARY_SUBSCR_LIST_INT 20 +#define BINARY_SUBSCR_TUPLE_INT 21 +#define CALL_ADAPTIVE 22 +#define CALL_PY_EXACT_ARGS 23 +#define CALL_PY_WITH_DEFAULTS 24 +#define COMPARE_OP_ADAPTIVE 26 +#define COMPARE_OP_FLOAT_JUMP 27 +#define COMPARE_OP_INT_JUMP 28 +#define COMPARE_OP_STR_JUMP 29 +#define EXTENDED_ARG_QUICK 34 +#define JUMP_BACKWARD_QUICK 38 +#define LOAD_ATTR_ADAPTIVE 39 +#define LOAD_ATTR_INSTANCE_VALUE 40 +#define LOAD_ATTR_MODULE 41 +#define LOAD_ATTR_SLOT 42 +#define LOAD_ATTR_WITH_HINT 43 +#define LOAD_CONST__LOAD_FAST 44 +#define LOAD_FAST__LOAD_CONST 45 +#define LOAD_FAST__LOAD_FAST 46 +#define LOAD_GLOBAL_ADAPTIVE 47 +#define LOAD_GLOBAL_BUILTIN 48 +#define LOAD_GLOBAL_MODULE 55 +#define LOAD_METHOD_ADAPTIVE 56 +#define LOAD_METHOD_CLASS 57 +#define LOAD_METHOD_MODULE 58 +#define LOAD_METHOD_NO_DICT 59 +#define LOAD_METHOD_WITH_DICT 62 +#define LOAD_METHOD_WITH_VALUES 63 +#define PRECALL_ADAPTIVE 64 +#define PRECALL_BOUND_METHOD 65 +#define PRECALL_BUILTIN_CLASS 66 +#define PRECALL_BUILTIN_FAST_WITH_KEYWORDS 67 +#define PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 72 +#define PRECALL_NO_KW_BUILTIN_FAST 73 +#define PRECALL_NO_KW_BUILTIN_O 76 +#define PRECALL_NO_KW_ISINSTANCE 77 +#define PRECALL_NO_KW_LEN 78 +#define PRECALL_NO_KW_LIST_APPEND 79 +#define PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST 80 +#define PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 81 +#define PRECALL_NO_KW_METHOD_DESCRIPTOR_O 113 +#define PRECALL_NO_KW_STR_1 121 +#define PRECALL_NO_KW_TUPLE_1 127 +#define PRECALL_NO_KW_TYPE_1 141 +#define PRECALL_PYFUNC 143 +#define RESUME_QUICK 150 +#define STORE_ATTR_ADAPTIVE 153 +#define STORE_ATTR_INSTANCE_VALUE 154 +#define STORE_ATTR_SLOT 158 +#define STORE_ATTR_WITH_HINT 159 +#define STORE_FAST__LOAD_FAST 161 +#define STORE_FAST__STORE_FAST 167 +#define STORE_SUBSCR_ADAPTIVE 168 +#define STORE_SUBSCR_DICT 169 +#define STORE_SUBSCR_LIST_INT 170 +#define UNPACK_SEQUENCE_ADAPTIVE 177 +#define UNPACK_SEQUENCE_LIST 178 +#define UNPACK_SEQUENCE_TUPLE 179 +#define UNPACK_SEQUENCE_TWO_TUPLE 180 +#define DO_TRACING 255 + +#define HAS_CONST(op) (false\ + || ((op) == 100) \ + || ((op) == 172) \ + ) -/* EXCEPT_HANDLER is a special, implicit block type which is created when - entering an except handler. It is not an opcode but we define it here - as we want it to be available to both frameobject.c and ceval.c, while - remaining private.*/ -#define EXCEPT_HANDLER 257 +#define NB_ADD 0 +#define NB_AND 1 +#define NB_FLOOR_DIVIDE 2 +#define NB_LSHIFT 3 +#define NB_MATRIX_MULTIPLY 4 +#define NB_MULTIPLY 5 +#define NB_REMAINDER 6 +#define NB_OR 7 +#define NB_POWER 8 +#define NB_RSHIFT 9 +#define NB_SUBTRACT 10 +#define NB_TRUE_DIVIDE 11 +#define NB_XOR 12 +#define NB_INPLACE_ADD 13 +#define NB_INPLACE_AND 14 +#define NB_INPLACE_FLOOR_DIVIDE 15 +#define NB_INPLACE_LSHIFT 16 +#define NB_INPLACE_MATRIX_MULTIPLY 17 +#define NB_INPLACE_MULTIPLY 18 +#define NB_INPLACE_REMAINDER 19 +#define NB_INPLACE_OR 20 +#define NB_INPLACE_POWER 21 +#define NB_INPLACE_RSHIFT 22 +#define NB_INPLACE_SUBTRACT 23 +#define NB_INPLACE_TRUE_DIVIDE 24 +#define NB_INPLACE_XOR 25 #define HAS_ARG(op) ((op) >= HAVE_ARGUMENT) +/* Reserve some bytecodes for internal use in the compiler. + * The value of 240 is arbitrary. */ +#define IS_ARTIFICIAL(op) ((op) > 240) + #ifdef __cplusplus } #endif diff --git a/include/patchlevel.h b/include/patchlevel.h index 1714f859..62740140 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -17,13 +17,13 @@ /* Version parsed out into numeric values */ /*--start constants--*/ #define PY_MAJOR_VERSION 3 -#define PY_MINOR_VERSION 10 -#define PY_MICRO_VERSION 7 +#define PY_MINOR_VERSION 11 +#define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.10.7" +#define PY_VERSION "3.11.0" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/include/py_curses.h b/include/py_curses.h index b70252d9..b2c7f1bb 100644 --- a/include/py_curses.h +++ b/include/py_curses.h @@ -77,7 +77,7 @@ typedef struct { static void **PyCurses_API; -#define PyCursesWindow_Type (*(PyTypeObject *) PyCurses_API[0]) +#define PyCursesWindow_Type (*_PyType_CAST(PyCurses_API[0])) #define PyCursesSetupTermCalled {if (! ((int (*)(void))PyCurses_API[1]) () ) return NULL;} #define PyCursesInitialised {if (! ((int (*)(void))PyCurses_API[2]) () ) return NULL;} #define PyCursesInitialisedColor {if (! ((int (*)(void))PyCurses_API[3]) () ) return NULL;} diff --git a/include/pybuffer.h b/include/pybuffer.h new file mode 100644 index 00000000..6893505e --- /dev/null +++ b/include/pybuffer.h @@ -0,0 +1,142 @@ +/* Public Py_buffer API */ + +#ifndef Py_BUFFER_H +#define Py_BUFFER_H +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030b0000 + +/* === New Buffer API ============================================ + * Limited API and stable ABI since Python 3.11 + * + * Py_buffer struct layout and size is now part of the stable abi3. The + * struct layout and size must not be changed in any way, as it would + * break the ABI. + * + */ + +typedef struct { + void *buf; + PyObject *obj; /* owned reference */ + Py_ssize_t len; + Py_ssize_t itemsize; /* This is Py_ssize_t so it can be + pointed to by strides in simple case.*/ + int readonly; + int ndim; + char *format; + Py_ssize_t *shape; + Py_ssize_t *strides; + Py_ssize_t *suboffsets; + void *internal; +} Py_buffer; + +/* Return 1 if the getbuffer function is available, otherwise return 0. */ +PyAPI_FUNC(int) PyObject_CheckBuffer(PyObject *obj); + +/* This is a C-API version of the getbuffer function call. It checks + to make sure object has the required function pointer and issues the + call. + + Returns -1 and raises an error on failure and returns 0 on success. */ +PyAPI_FUNC(int) PyObject_GetBuffer(PyObject *obj, Py_buffer *view, + int flags); + +/* Get the memory area pointed to by the indices for the buffer given. + Note that view->ndim is the assumed size of indices. */ +PyAPI_FUNC(void *) PyBuffer_GetPointer(const Py_buffer *view, const Py_ssize_t *indices); + +/* Return the implied itemsize of the data-format area from a + struct-style description. */ +PyAPI_FUNC(Py_ssize_t) PyBuffer_SizeFromFormat(const char *format); + +/* Implementation in memoryobject.c */ +PyAPI_FUNC(int) PyBuffer_ToContiguous(void *buf, const Py_buffer *view, + Py_ssize_t len, char order); + +PyAPI_FUNC(int) PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, + Py_ssize_t len, char order); + +/* Copy len bytes of data from the contiguous chunk of memory + pointed to by buf into the buffer exported by obj. Return + 0 on success and return -1 and raise a PyBuffer_Error on + error (i.e. the object does not have a buffer interface or + it is not working). + + If fort is 'F', then if the object is multi-dimensional, + then the data will be copied into the array in + Fortran-style (first dimension varies the fastest). If + fort is 'C', then the data will be copied into the array + in C-style (last dimension varies the fastest). If fort + is 'A', then it does not matter and the copy will be made + in whatever way is more efficient. */ +PyAPI_FUNC(int) PyObject_CopyData(PyObject *dest, PyObject *src); + +/* Copy the data from the src buffer to the buffer of destination. */ +PyAPI_FUNC(int) PyBuffer_IsContiguous(const Py_buffer *view, char fort); + +/*Fill the strides array with byte-strides of a contiguous + (Fortran-style if fort is 'F' or C-style otherwise) + array of the given shape with the given number of bytes + per element. */ +PyAPI_FUNC(void) PyBuffer_FillContiguousStrides(int ndims, + Py_ssize_t *shape, + Py_ssize_t *strides, + int itemsize, + char fort); + +/* Fills in a buffer-info structure correctly for an exporter + that can only share a contiguous chunk of memory of + "unsigned bytes" of the given length. + + Returns 0 on success and -1 (with raising an error) on error. */ +PyAPI_FUNC(int) PyBuffer_FillInfo(Py_buffer *view, PyObject *o, void *buf, + Py_ssize_t len, int readonly, + int flags); + +/* Releases a Py_buffer obtained from getbuffer ParseTuple's "s*". */ +PyAPI_FUNC(void) PyBuffer_Release(Py_buffer *view); + +/* Maximum number of dimensions */ +#define PyBUF_MAX_NDIM 64 + +/* Flags for getting buffers */ +#define PyBUF_SIMPLE 0 +#define PyBUF_WRITABLE 0x0001 + +#ifndef Py_LIMITED_API +/* we used to include an E, backwards compatible alias */ +#define PyBUF_WRITEABLE PyBUF_WRITABLE +#endif + +#define PyBUF_FORMAT 0x0004 +#define PyBUF_ND 0x0008 +#define PyBUF_STRIDES (0x0010 | PyBUF_ND) +#define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES) +#define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES) +#define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES) +#define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES) + +#define PyBUF_CONTIG (PyBUF_ND | PyBUF_WRITABLE) +#define PyBUF_CONTIG_RO (PyBUF_ND) + +#define PyBUF_STRIDED (PyBUF_STRIDES | PyBUF_WRITABLE) +#define PyBUF_STRIDED_RO (PyBUF_STRIDES) + +#define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT) +#define PyBUF_RECORDS_RO (PyBUF_STRIDES | PyBUF_FORMAT) + +#define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT) +#define PyBUF_FULL_RO (PyBUF_INDIRECT | PyBUF_FORMAT) + + +#define PyBUF_READ 0x100 +#define PyBUF_WRITE 0x200 + +#endif /* !Py_LIMITED_API || Py_LIMITED_API >= 3.11 */ + +#ifdef __cplusplus +} +#endif +#endif /* Py_BUFFER_H */ diff --git a/include/pyconfig.h b/include/pyconfig.h index 103e647a..959b851d 100644 --- a/include/pyconfig.h +++ b/include/pyconfig.h @@ -58,7 +58,6 @@ WIN32 is still required for the locale module. #include -#define HAVE_HYPOT #define HAVE_STRFTIME #define DONT_HAVE_SIG_ALARM #define DONT_HAVE_SIG_PAUSE @@ -67,9 +66,6 @@ WIN32 is still required for the locale module. #define MS_WIN32 /* only support win32 and greater. */ #define MS_WINDOWS -#ifndef PYTHONPATH -# define PYTHONPATH L".\\DLLs;.\\lib" -#endif #define NT_THREADS #define WITH_THREAD #ifndef NETSCAPE_PI @@ -117,20 +113,30 @@ WIN32 is still required for the locale module. #define MS_WIN64 #endif -/* set the COMPILER */ +/* set the COMPILER and support tier + * + * win_amd64 MSVC (x86_64-pc-windows-msvc): 1 + * win32 MSVC (i686-pc-windows-msvc): 1 + * win_arm64 MSVC (aarch64-pc-windows-msvc): 3 + * other archs and ICC: 0 + */ #ifdef MS_WIN64 #if defined(_M_X64) || defined(_M_AMD64) #if defined(__INTEL_COMPILER) #define COMPILER ("[ICC v." _Py_STRINGIZE(__INTEL_COMPILER) " 64 bit (amd64) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") +#define PY_SUPPORT_TIER 0 #else #define COMPILER _Py_PASTE_VERSION("64 bit (AMD64)") +#define PY_SUPPORT_TIER 1 #endif /* __INTEL_COMPILER */ #define PYD_PLATFORM_TAG "win_amd64" #elif defined(_M_ARM64) #define COMPILER _Py_PASTE_VERSION("64 bit (ARM64)") +#define PY_SUPPORT_TIER 3 #define PYD_PLATFORM_TAG "win_arm64" #else #define COMPILER _Py_PASTE_VERSION("64 bit (Unknown)") +#define PY_SUPPORT_TIER 0 #endif #endif /* MS_WIN64 */ @@ -166,8 +172,10 @@ WIN32 is still required for the locale module. /* Define like size_t, omitting the "unsigned" */ #ifdef MS_WIN64 typedef __int64 Py_ssize_t; +# define PY_SSIZE_T_MAX LLONG_MAX #else typedef _W64 int Py_ssize_t; +# define PY_SSIZE_T_MAX INT_MAX #endif #define HAVE_PY_SSIZE_T 1 @@ -175,25 +183,24 @@ typedef _W64 int Py_ssize_t; #if defined(_M_IX86) #if defined(__INTEL_COMPILER) #define COMPILER ("[ICC v." _Py_STRINGIZE(__INTEL_COMPILER) " 32 bit (Intel) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") +#define PY_SUPPORT_TIER 0 #else #define COMPILER _Py_PASTE_VERSION("32 bit (Intel)") +#define PY_SUPPORT_TIER 1 #endif /* __INTEL_COMPILER */ #define PYD_PLATFORM_TAG "win32" #elif defined(_M_ARM) #define COMPILER _Py_PASTE_VERSION("32 bit (ARM)") #define PYD_PLATFORM_TAG "win_arm32" +#define PY_SUPPORT_TIER 0 #else #define COMPILER _Py_PASTE_VERSION("32 bit (Unknown)") +#define PY_SUPPORT_TIER 0 #endif #endif /* MS_WIN32 && !MS_WIN64 */ typedef int pid_t; -#include -#define Py_IS_NAN _isnan -#define Py_IS_INFINITY(X) (!_finite(X) && !_isnan(X)) -#define Py_IS_FINITE(X) _finite(X) - /* define some ANSI types that are not defined in earlier Win headers */ #if _MSC_VER >= 1200 /* This file only exists in VC 6.0 or higher */ @@ -268,11 +275,11 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ file in their Makefile (other compilers are generally taken care of by distutils.) */ # if defined(_DEBUG) -# pragma comment(lib,"python310_d.lib") +# pragma comment(lib,"python311_d.lib") # elif defined(Py_LIMITED_API) # pragma comment(lib,"python3.lib") # else -# pragma comment(lib,"python310.lib") +# pragma comment(lib,"python311.lib") # endif /* _DEBUG */ # endif /* _MSC_VER */ # endif /* Py_BUILD_CORE */ @@ -353,20 +360,6 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ /* Fairly standard from here! */ -/* Define to 1 if you have the `copysign' function. */ -#define HAVE_COPYSIGN 1 - -/* Define to 1 if you have the `round' function. */ -#if _MSC_VER >= 1800 -#define HAVE_ROUND 1 -#endif - -/* Define to 1 if you have the `isinf' macro. */ -#define HAVE_DECL_ISINF 1 - -/* Define to 1 if you have the `isnan' function. */ -#define HAVE_DECL_ISNAN 1 - /* Define if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ @@ -483,6 +476,9 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ /* Use Python's own small-block memory-allocator. */ #define WITH_PYMALLOC 1 +/* Define if you want to compile in object freelists optimization */ +#define WITH_FREELISTS 1 + /* Define if you have clock. */ /* #define HAVE_CLOCK */ @@ -534,6 +530,9 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ /* Define if you have siginterrupt. */ /* #undef HAVE_SIGINTERRUPT */ +/* Define to 1 if you have the `shutdown' function. */ +#define HAVE_SHUTDOWN 1 + /* Define if you have symlink. */ /* #undef HAVE_SYMLINK */ @@ -546,6 +545,9 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ /* Define if you have times. */ /* #undef HAVE_TIMES */ +/* Define to 1 if you have the `umask' function. */ +#define HAVE_UMASK 1 + /* Define if you have uname. */ /* #undef HAVE_UNAME */ @@ -676,8 +678,28 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ /* Define to 1 if you have the `erfc' function. */ #define HAVE_ERFC 1 -/* Define if you have the 'inet_pton' function. */ +// netdb.h functions (provided by winsock.h) +#define HAVE_GETHOSTNAME 1 +#define HAVE_GETHOSTBYADDR 1 +#define HAVE_GETHOSTBYNAME 1 +#define HAVE_GETPROTOBYNAME 1 +#define HAVE_GETSERVBYNAME 1 +#define HAVE_GETSERVBYPORT 1 +// sys/socket.h functions (provided by winsock.h) #define HAVE_INET_PTON 1 +#define HAVE_INET_NTOA 1 +#define HAVE_ACCEPT 1 +#define HAVE_BIND 1 +#define HAVE_CONNECT 1 +#define HAVE_GETSOCKNAME 1 +#define HAVE_LISTEN 1 +#define HAVE_RECVFROM 1 +#define HAVE_SENDTO 1 +#define HAVE_SETSOCKOPT 1 +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the `dup' function. */ +#define HAVE_DUP 1 /* framework name */ #define _PYTHONFRAMEWORK "" @@ -685,6 +707,4 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ /* Define if libssl has X509_VERIFY_PARAM_set1_host and related function */ #define HAVE_X509_VERIFY_PARAM_SET1_HOST 1 -#define PLATLIBDIR "lib" - #endif /* !Py_CONFIG_H */ diff --git a/include/pyerrors.h b/include/pyerrors.h index f5d1c711..34e3de33 100644 --- a/include/pyerrors.h +++ b/include/pyerrors.h @@ -18,6 +18,10 @@ PyAPI_FUNC(PyObject *) PyErr_Occurred(void); PyAPI_FUNC(void) PyErr_Clear(void); PyAPI_FUNC(void) PyErr_Fetch(PyObject **, PyObject **, PyObject **); PyAPI_FUNC(void) PyErr_Restore(PyObject *, PyObject *, PyObject *); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030b0000 +PyAPI_FUNC(PyObject*) PyErr_GetHandledException(void); +PyAPI_FUNC(void) PyErr_SetHandledException(PyObject *); +#endif #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 PyAPI_FUNC(void) PyErr_GetExcInfo(PyObject **, PyObject **, PyObject **); PyAPI_FUNC(void) PyErr_SetExcInfo(PyObject *, PyObject *, PyObject *); @@ -60,11 +64,14 @@ PyAPI_FUNC(const char *) PyExceptionClass_Name(PyObject *); #define PyExceptionInstance_Class(x) ((PyObject*)Py_TYPE(x)) +#define _PyBaseExceptionGroup_Check(x) \ + PyObject_TypeCheck(x, (PyTypeObject *)PyExc_BaseExceptionGroup) /* Predefined exceptions */ PyAPI_DATA(PyObject *) PyExc_BaseException; PyAPI_DATA(PyObject *) PyExc_Exception; +PyAPI_DATA(PyObject *) PyExc_BaseExceptionGroup; #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 PyAPI_DATA(PyObject *) PyExc_StopAsyncIteration; #endif @@ -314,7 +321,7 @@ PyAPI_FUNC(int) PyOS_vsnprintf(char *str, size_t size, const char *format, va_l #ifndef Py_LIMITED_API # define Py_CPYTHON_ERRORS_H -# include "cpython/pyerrors.h" +# include "cpython/pyerrors.h" # undef Py_CPYTHON_ERRORS_H #endif diff --git a/include/pyframe.h b/include/pyframe.h index 38162242..13d52312 100644 --- a/include/pyframe.h +++ b/include/pyframe.h @@ -9,13 +9,17 @@ extern "C" { #endif -typedef struct _frame PyFrameObject; - /* Return the line of code the frame is currently executing. */ PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *); PyAPI_FUNC(PyCodeObject *) PyFrame_GetCode(PyFrameObject *frame); +#ifndef Py_LIMITED_API +# define Py_CPYTHON_PYFRAME_H +# include "cpython/pyframe.h" +# undef Py_CPYTHON_PYFRAME_H +#endif + #ifdef __cplusplus } #endif diff --git a/include/pyhash.h b/include/pyhash.h index a314ea90..182d223f 100644 --- a/include/pyhash.h +++ b/include/pyhash.h @@ -114,11 +114,10 @@ PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void); /* hash algorithm selection * - * The values for Py_HASH_SIPHASH24 and Py_HASH_FNV are hard-coded in the + * The values for Py_HASH_* are hard-coded in the * configure script. * - * - FNV is available on all platforms and architectures. - * - SIPHASH24 only works on platforms that don't require aligned memory for integers. + * - FNV and SIPHASH* are available on all platforms and architectures. * - With EXTERNAL embedders can provide an alternative implementation with:: * * PyHash_FuncDef PyHash_Func = {...}; @@ -128,10 +127,11 @@ PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void); #define Py_HASH_EXTERNAL 0 #define Py_HASH_SIPHASH24 1 #define Py_HASH_FNV 2 +#define Py_HASH_SIPHASH13 3 #ifndef Py_HASH_ALGORITHM # ifndef HAVE_ALIGNED_REQUIRED -# define Py_HASH_ALGORITHM Py_HASH_SIPHASH24 +# define Py_HASH_ALGORITHM Py_HASH_SIPHASH13 # else # define Py_HASH_ALGORITHM Py_HASH_FNV # endif /* uint64_t && uint32_t && aligned */ diff --git a/include/pylifecycle.h b/include/pylifecycle.h index 2df7fe6e..e4c3b09c 100644 --- a/include/pylifecycle.h +++ b/include/pylifecycle.h @@ -34,10 +34,10 @@ PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv); PyAPI_FUNC(int) Py_BytesMain(int argc, char **argv); /* In pathconfig.c */ -PyAPI_FUNC(void) Py_SetProgramName(const wchar_t *); +Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetProgramName(const wchar_t *); PyAPI_FUNC(wchar_t *) Py_GetProgramName(void); -PyAPI_FUNC(void) Py_SetPythonHome(const wchar_t *); +Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetPythonHome(const wchar_t *); PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void); PyAPI_FUNC(wchar_t *) Py_GetProgramFullPath(void); @@ -45,7 +45,7 @@ PyAPI_FUNC(wchar_t *) Py_GetProgramFullPath(void); PyAPI_FUNC(wchar_t *) Py_GetPrefix(void); PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void); PyAPI_FUNC(wchar_t *) Py_GetPath(void); -PyAPI_FUNC(void) Py_SetPath(const wchar_t *); +Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetPath(const wchar_t *); #ifdef MS_WINDOWS int _Py_CheckPython3(void); #endif @@ -62,9 +62,13 @@ typedef void (*PyOS_sighandler_t)(int); PyAPI_FUNC(PyOS_sighandler_t) PyOS_getsig(int); PyAPI_FUNC(PyOS_sighandler_t) PyOS_setsig(int, PyOS_sighandler_t); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030B0000 +PyAPI_DATA(const unsigned long) Py_Version; +#endif + #ifndef Py_LIMITED_API # define Py_CPYTHON_PYLIFECYCLE_H -# include "cpython/pylifecycle.h" +# include "cpython/pylifecycle.h" # undef Py_CPYTHON_PYLIFECYCLE_H #endif diff --git a/include/pymacro.h b/include/pymacro.h index 202b936d..90ad8f07 100644 --- a/include/pymacro.h +++ b/include/pymacro.h @@ -1,6 +1,25 @@ #ifndef Py_PYMACRO_H #define Py_PYMACRO_H +// gh-91782: On FreeBSD 12, if the _POSIX_C_SOURCE and _XOPEN_SOURCE macros are +// defined, disables C11 support and does not define +// the static_assert() macro. Define the static_assert() macro in Python until +// suports C11: +// https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=255290 +#if defined(__FreeBSD__) && !defined(static_assert) +# define static_assert _Static_assert +#endif + +// static_assert is defined in glibc from version 2.16. Before it requires +// compiler support (gcc >= 4.6) and is called _Static_assert. +// In C++ 11 static_assert is a keyword, redefining is undefined behaviour. +#if (defined(__GLIBC__) \ + && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 16)) \ + && !(defined(__cplusplus) && __cplusplus >= 201103L) \ + && !defined(static_assert)) +# define static_assert _Static_assert +#endif + /* Minimum value between x and y */ #define Py_MIN(x, y) (((x) > (y)) ? (y) : (x)) @@ -129,4 +148,8 @@ Py_FatalError("Unreachable C code path reached") #endif +// Prevent using an expression as a l-value. +// For example, "int x; _Py_RVALUE(x) = 1;" fails with a compiler error. +#define _Py_RVALUE(EXPR) ((void)0, (EXPR)) + #endif /* Py_PYMACRO_H */ diff --git a/include/pymath.h b/include/pymath.h index f8697243..772b67e4 100644 --- a/include/pymath.h +++ b/include/pymath.h @@ -1,42 +1,9 @@ +// Symbols and macros to supply platform-independent interfaces to mathematical +// functions and constants. + #ifndef Py_PYMATH_H #define Py_PYMATH_H -#include "pyconfig.h" /* include for defines */ - -/************************************************************************** -Symbols and macros to supply platform-independent interfaces to mathematical -functions and constants -**************************************************************************/ - -/* Python provides implementations for copysign, round and hypot in - * Python/pymath.c just in case your math library doesn't provide the - * functions. - * - *Note: PC/pyconfig.h defines copysign as _copysign - */ -#ifndef HAVE_COPYSIGN -extern double copysign(double, double); -#endif - -#ifndef HAVE_ROUND -extern double round(double); -#endif - -#ifndef HAVE_HYPOT -extern double hypot(double, double); -#endif - -/* extra declarations */ -#ifndef _MSC_VER -#ifndef __STDC__ -extern double fmod (double, double); -extern double frexp (double, int *); -extern double ldexp (double, int); -extern double modf (double, double *); -extern double pow(double, double); -#endif /* __STDC__ */ -#endif /* _MSC_VER */ - /* High precision definition of pi and e (Euler) * The values are taken from libc6's math.h. */ @@ -60,84 +27,17 @@ extern double pow(double, double); #define Py_MATH_TAU 6.2831853071795864769252867665590057683943L #endif - -/* On x86, Py_FORCE_DOUBLE forces a floating-point number out of an x87 FPU - register and into a 64-bit memory location, rounding from extended - precision to double precision in the process. On other platforms it does - nothing. */ - -/* we take double rounding as evidence of x87 usage */ -#ifndef Py_LIMITED_API -#ifndef Py_FORCE_DOUBLE -# ifdef X87_DOUBLE_ROUNDING -PyAPI_FUNC(double) _Py_force_double(double); -# define Py_FORCE_DOUBLE(X) (_Py_force_double(X)) -# else -# define Py_FORCE_DOUBLE(X) (X) -# endif -#endif -#endif - -#ifndef Py_LIMITED_API -#ifdef HAVE_GCC_ASM_FOR_X87 -PyAPI_FUNC(unsigned short) _Py_get_387controlword(void); -PyAPI_FUNC(void) _Py_set_387controlword(unsigned short); -#endif -#endif - -/* Py_IS_NAN(X) - * Return 1 if float or double arg is a NaN, else 0. - * Caution: - * X is evaluated more than once. - * This may not work on all platforms. Each platform has *some* - * way to spell this, though -- override in pyconfig.h if you have - * a platform where it doesn't work. - * Note: PC/pyconfig.h defines Py_IS_NAN as _isnan - */ -#ifndef Py_IS_NAN -#if defined HAVE_DECL_ISNAN && HAVE_DECL_ISNAN == 1 +// Py_IS_NAN(X) +// Return 1 if float or double arg is a NaN, else 0. #define Py_IS_NAN(X) isnan(X) -#else -#define Py_IS_NAN(X) ((X) != (X)) -#endif -#endif -/* Py_IS_INFINITY(X) - * Return 1 if float or double arg is an infinity, else 0. - * Caution: - * X is evaluated more than once. - * This implementation may set the underflow flag if |X| is very small; - * it really can't be implemented correctly (& easily) before C99. - * Override in pyconfig.h if you have a better spelling on your platform. - * Py_FORCE_DOUBLE is used to avoid getting false negatives from a - * non-infinite value v sitting in an 80-bit x87 register such that - * v becomes infinite when spilled from the register to 64-bit memory. - * Note: PC/pyconfig.h defines Py_IS_INFINITY as _isinf - */ -#ifndef Py_IS_INFINITY -# if defined HAVE_DECL_ISINF && HAVE_DECL_ISINF == 1 -# define Py_IS_INFINITY(X) isinf(X) -# else -# define Py_IS_INFINITY(X) ((X) && \ - (Py_FORCE_DOUBLE(X)*0.5 == Py_FORCE_DOUBLE(X))) -# endif -#endif +// Py_IS_INFINITY(X) +// Return 1 if float or double arg is an infinity, else 0. +#define Py_IS_INFINITY(X) isinf(X) -/* Py_IS_FINITE(X) - * Return 1 if float or double arg is neither infinite nor NAN, else 0. - * Some compilers (e.g. VisualStudio) have intrinsics for this, so a special - * macro for this particular test is useful - * Note: PC/pyconfig.h defines Py_IS_FINITE as _finite - */ -#ifndef Py_IS_FINITE -#if defined HAVE_DECL_ISFINITE && HAVE_DECL_ISFINITE == 1 +// Py_IS_FINITE(X) +// Return 1 if float or double arg is neither infinite nor NAN, else 0. #define Py_IS_FINITE(X) isfinite(X) -#elif defined HAVE_FINITE -#define Py_IS_FINITE(X) finite(X) -#else -#define Py_IS_FINITE(X) (!Py_IS_INFINITY(X) && !Py_IS_NAN(X)) -#endif -#endif /* HUGE_VAL is supposed to expand to a positive double infinity. Python * uses Py_HUGE_VAL instead because some platforms are broken in this @@ -147,84 +47,19 @@ PyAPI_FUNC(void) _Py_set_387controlword(unsigned short); * config to #define Py_HUGE_VAL to something that works on your platform. */ #ifndef Py_HUGE_VAL -#define Py_HUGE_VAL HUGE_VAL +# define Py_HUGE_VAL HUGE_VAL #endif -/* Py_NAN - * A value that evaluates to a NaN. On IEEE 754 platforms INF*0 or - * INF/INF works. Define Py_NO_NAN in pyconfig.h if your platform - * doesn't support NaNs. - */ -#if !defined(Py_NAN) && !defined(Py_NO_NAN) -#if !defined(__INTEL_COMPILER) - #define Py_NAN (Py_HUGE_VAL * 0.) -#else /* __INTEL_COMPILER */ - #if defined(ICC_NAN_STRICT) - #pragma float_control(push) - #pragma float_control(precise, on) - #pragma float_control(except, on) - #if defined(_MSC_VER) - __declspec(noinline) - #else /* Linux */ - __attribute__((noinline)) - #endif /* _MSC_VER */ - static double __icc_nan() - { - return sqrt(-1.0); - } - #pragma float_control (pop) - #define Py_NAN __icc_nan() - #else /* ICC_NAN_RELAXED as default for Intel Compiler */ - static const union { unsigned char buf[8]; double __icc_nan; } __nan_store = {0,0,0,0,0,0,0xf8,0x7f}; - #define Py_NAN (__nan_store.__icc_nan) - #endif /* ICC_NAN_STRICT */ -#endif /* __INTEL_COMPILER */ -#endif - -/* Py_OVERFLOWED(X) - * Return 1 iff a libm function overflowed. Set errno to 0 before calling - * a libm function, and invoke this macro after, passing the function - * result. - * Caution: - * This isn't reliable. C99 no longer requires libm to set errno under - * any exceptional condition, but does require +- HUGE_VAL return - * values on overflow. A 754 box *probably* maps HUGE_VAL to a - * double infinity, and we're cool if that's so, unless the input - * was an infinity and an infinity is the expected result. A C89 - * system sets errno to ERANGE, so we check for that too. We're - * out of luck if a C99 754 box doesn't map HUGE_VAL to +Inf, or - * if the returned result is a NaN, or if a C89 box returns HUGE_VAL - * in non-overflow cases. - * X is evaluated more than once. - * Some platforms have better way to spell this, so expect some #ifdef'ery. - * - * OpenBSD uses 'isinf()' because a compiler bug on that platform causes - * the longer macro version to be mis-compiled. This isn't optimal, and - * should be removed once a newer compiler is available on that platform. - * The system that had the failure was running OpenBSD 3.2 on Intel, with - * gcc 2.95.3. - * - * According to Tim's checkin, the FreeBSD systems use isinf() to work - * around a FPE bug on that platform. - */ -#if defined(__FreeBSD__) || defined(__OpenBSD__) -#define Py_OVERFLOWED(X) isinf(X) +// Py_NAN: Value that evaluates to a quiet Not-a-Number (NaN). +#if !defined(Py_NAN) +# if _Py__has_builtin(__builtin_nan) + // Built-in implementation of the ISO C99 function nan(): quiet NaN. +# define Py_NAN (__builtin_nan("")) #else -#define Py_OVERFLOWED(X) ((X) != 0.0 && (errno == ERANGE || \ - (X) == Py_HUGE_VAL || \ - (X) == -Py_HUGE_VAL)) + // Use C99 NAN constant: quiet Not-A-Number. + // NAN is a float, Py_NAN is a double: cast to double. +# define Py_NAN ((double)NAN) +# endif #endif -/* Return whether integral type *type* is signed or not. */ -#define _Py_IntegralTypeSigned(type) ((type)(-1) < 0) -/* Return the maximum value of integral type *type*. */ -#define _Py_IntegralTypeMax(type) ((_Py_IntegralTypeSigned(type)) ? (((((type)1 << (sizeof(type)*CHAR_BIT - 2)) - 1) << 1) + 1) : ~(type)0) -/* Return the minimum value of integral type *type*. */ -#define _Py_IntegralTypeMin(type) ((_Py_IntegralTypeSigned(type)) ? -_Py_IntegralTypeMax(type) - 1 : 0) -/* Check whether *v* is in the range of integral type *type*. This is most - * useful if *v* is floating-point, since demoting a floating-point *v* to an - * integral type that cannot represent *v*'s integral part is undefined - * behavior. */ -#define _Py_InIntegralTypeRange(type, v) (_Py_IntegralTypeMin(type) <= v && v <= _Py_IntegralTypeMax(type)) - #endif /* Py_PYMATH_H */ diff --git a/include/pymem.h b/include/pymem.h index 66cdb0d2..c15ad10d 100644 --- a/include/pymem.h +++ b/include/pymem.h @@ -93,7 +93,7 @@ PyAPI_FUNC(void) PyMem_Free(void *ptr); #ifndef Py_LIMITED_API # define Py_CPYTHON_PYMEM_H -# include "cpython/pymem.h" +# include "cpython/pymem.h" # undef Py_CPYTHON_PYMEM_H #endif diff --git a/include/pyport.h b/include/pyport.h index 6ab0ae40..93250f4e 100644 --- a/include/pyport.h +++ b/include/pyport.h @@ -5,6 +5,33 @@ #include +#include +#ifndef UCHAR_MAX +# error "limits.h must define UCHAR_MAX" +#endif +#if UCHAR_MAX != 255 +# error "Python's source code assumes C's unsigned char is an 8-bit type" +#endif + + +// Macro to use C++ static_cast<> in the Python C API. +#ifdef __cplusplus +# define _Py_STATIC_CAST(type, expr) static_cast(expr) +#else +# define _Py_STATIC_CAST(type, expr) ((type)(expr)) +#endif +// Macro to use the more powerful/dangerous C-style cast even in C++. +#define _Py_CAST(type, expr) ((type)(expr)) + +// Static inline functions should use _Py_NULL rather than using directly NULL +// to prevent C++ compiler warnings. On C++11 and newer, _Py_NULL is defined as +// nullptr. +#if defined(__cplusplus) && __cplusplus >= 201103 +# define _Py_NULL nullptr +#else +# define _Py_NULL NULL +#endif + /* Defines to build Python and its standard library: * @@ -77,16 +104,12 @@ Used in: Py_SAFE_DOWNCAST #define PY_INT32_T int32_t #define PY_INT64_T int64_t -/* If PYLONG_BITS_IN_DIGIT is not defined then we'll use 30-bit digits if all - the necessary integer types are available, and we're on a 64-bit platform - (as determined by SIZEOF_VOID_P); otherwise we use 15-bit digits. */ - +/* PYLONG_BITS_IN_DIGIT describes the number of bits per "digit" (limb) in the + * PyLongObject implementation (longintrepr.h). It's currently either 30 or 15, + * defaulting to 30. The 15-bit digit option may be removed in the future. + */ #ifndef PYLONG_BITS_IN_DIGIT -#if SIZEOF_VOID_P >= 8 #define PYLONG_BITS_IN_DIGIT 30 -#else -#define PYLONG_BITS_IN_DIGIT 15 -#endif #endif /* uintptr_t is the C9X name for an unsigned integral type such that a @@ -100,17 +123,23 @@ typedef intptr_t Py_intptr_t; /* Py_ssize_t is a signed integral type such that sizeof(Py_ssize_t) == * sizeof(size_t). C99 doesn't define such a thing directly (size_t is an * unsigned integral type). See PEP 353 for details. + * PY_SSIZE_T_MAX is the largest positive value of type Py_ssize_t. */ #ifdef HAVE_PY_SSIZE_T #elif HAVE_SSIZE_T typedef ssize_t Py_ssize_t; +# define PY_SSIZE_T_MAX SSIZE_MAX #elif SIZEOF_VOID_P == SIZEOF_SIZE_T typedef Py_intptr_t Py_ssize_t; +# define PY_SSIZE_T_MAX INTPTR_MAX #else # error "Python needs a typedef for Py_ssize_t in pyport.h." #endif +/* Smallest negative value of type Py_ssize_t. */ +#define PY_SSIZE_T_MIN (-PY_SSIZE_T_MAX-1) + /* Py_hash_t is the same size as a pointer. */ #define SIZEOF_PY_HASH_T SIZEOF_SIZE_T typedef Py_ssize_t Py_hash_t; @@ -118,21 +147,12 @@ typedef Py_ssize_t Py_hash_t; #define SIZEOF_PY_UHASH_T SIZEOF_SIZE_T typedef size_t Py_uhash_t; -/* Only used for compatibility with code that may not be PY_SSIZE_T_CLEAN. */ -#ifdef PY_SSIZE_T_CLEAN +/* Now PY_SSIZE_T_CLEAN is mandatory. This is just for backward compatibility. */ typedef Py_ssize_t Py_ssize_clean_t; -#else -typedef int Py_ssize_clean_t; -#endif /* Largest possible value of size_t. */ #define PY_SIZE_MAX SIZE_MAX -/* Largest positive value of type Py_ssize_t. */ -#define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1)) -/* Smallest negative value of type Py_ssize_t. */ -#define PY_SSIZE_T_MIN (-PY_SSIZE_T_MAX-1) - /* Macro kept for backward compatibility: use "z" in new code. * * PY_FORMAT_SIZE_T is a platform-specific modifier for use in a printf @@ -170,23 +190,12 @@ typedef int Py_ssize_clean_t; * Py_LOCAL_INLINE does the same thing, and also explicitly requests inlining, * for platforms that support that. * - * If PY_LOCAL_AGGRESSIVE is defined before python.h is included, more - * "aggressive" inlining/optimization is enabled for the entire module. This - * may lead to code bloat, and may slow things down for those reasons. It may - * also lead to errors, if the code relies on pointer aliasing. Use with - * care. - * * NOTE: You can only use this for functions that are entirely local to a * module; functions that are exported via method tables, callbacks, etc, * should keep using static. */ #if defined(_MSC_VER) -# if defined(PY_LOCAL_AGGRESSIVE) - /* enable more aggressive optimization for MSVC */ - /* active in both release and debug builds - see bpo-43271 */ -# pragma optimize("gt", on) -#endif /* ignore warnings if the compiler decides not to inline a function */ # pragma warning(disable: 4710) /* fastest possible local call under MSVC */ @@ -197,11 +206,10 @@ typedef int Py_ssize_clean_t; # define Py_LOCAL_INLINE(type) static inline type #endif -/* Py_MEMCPY is kept for backwards compatibility, - * see https://bugs.python.org/issue28126 */ -#define Py_MEMCPY memcpy - -#include +// bpo-28126: Py_MEMCPY is kept for backwards compatibility, +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 +# define Py_MEMCPY memcpy +#endif #ifdef HAVE_IEEEFP_H #include /* needed for 'finite' declaration on some platforms */ @@ -213,17 +221,10 @@ typedef int Py_ssize_clean_t; * WRAPPER FOR and/or * ********************************************/ -#ifdef TIME_WITH_SYS_TIME -#include -#include -#else /* !TIME_WITH_SYS_TIME */ #ifdef HAVE_SYS_TIME_H #include -#else /* !HAVE_SYS_TIME_H */ +#endif #include -#endif /* !HAVE_SYS_TIME_H */ -#endif /* !TIME_WITH_SYS_TIME */ - /****************************** * WRAPPER FOR * @@ -314,189 +315,11 @@ extern "C" { * VALUE may be evaluated more than once. */ #ifdef Py_DEBUG -#define Py_SAFE_DOWNCAST(VALUE, WIDE, NARROW) \ - (assert((WIDE)(NARROW)(VALUE) == (VALUE)), (NARROW)(VALUE)) +# define Py_SAFE_DOWNCAST(VALUE, WIDE, NARROW) \ + (assert(_Py_STATIC_CAST(WIDE, _Py_STATIC_CAST(NARROW, (VALUE))) == (VALUE)), \ + _Py_STATIC_CAST(NARROW, (VALUE))) #else -#define Py_SAFE_DOWNCAST(VALUE, WIDE, NARROW) (NARROW)(VALUE) -#endif - -/* Py_SET_ERRNO_ON_MATH_ERROR(x) - * If a libm function did not set errno, but it looks like the result - * overflowed or not-a-number, set errno to ERANGE or EDOM. Set errno - * to 0 before calling a libm function, and invoke this macro after, - * passing the function result. - * Caution: - * This isn't reliable. See Py_OVERFLOWED comments. - * X is evaluated more than once. - */ -#if defined(__FreeBSD__) || defined(__OpenBSD__) || (defined(__hpux) && defined(__ia64)) -#define _Py_SET_EDOM_FOR_NAN(X) if (isnan(X)) errno = EDOM; -#else -#define _Py_SET_EDOM_FOR_NAN(X) ; -#endif -#define Py_SET_ERRNO_ON_MATH_ERROR(X) \ - do { \ - if (errno == 0) { \ - if ((X) == Py_HUGE_VAL || (X) == -Py_HUGE_VAL) \ - errno = ERANGE; \ - else _Py_SET_EDOM_FOR_NAN(X) \ - } \ - } while(0) - -/* Py_SET_ERANGE_IF_OVERFLOW(x) - * An alias of Py_SET_ERRNO_ON_MATH_ERROR for backward-compatibility. - */ -#define Py_SET_ERANGE_IF_OVERFLOW(X) Py_SET_ERRNO_ON_MATH_ERROR(X) - -/* Py_ADJUST_ERANGE1(x) - * Py_ADJUST_ERANGE2(x, y) - * Set errno to 0 before calling a libm function, and invoke one of these - * macros after, passing the function result(s) (Py_ADJUST_ERANGE2 is useful - * for functions returning complex results). This makes two kinds of - * adjustments to errno: (A) If it looks like the platform libm set - * errno=ERANGE due to underflow, clear errno. (B) If it looks like the - * platform libm overflowed but didn't set errno, force errno to ERANGE. In - * effect, we're trying to force a useful implementation of C89 errno - * behavior. - * Caution: - * This isn't reliable. See Py_OVERFLOWED comments. - * X and Y may be evaluated more than once. - */ -#define Py_ADJUST_ERANGE1(X) \ - do { \ - if (errno == 0) { \ - if ((X) == Py_HUGE_VAL || (X) == -Py_HUGE_VAL) \ - errno = ERANGE; \ - } \ - else if (errno == ERANGE && (X) == 0.0) \ - errno = 0; \ - } while(0) - -#define Py_ADJUST_ERANGE2(X, Y) \ - do { \ - if ((X) == Py_HUGE_VAL || (X) == -Py_HUGE_VAL || \ - (Y) == Py_HUGE_VAL || (Y) == -Py_HUGE_VAL) { \ - if (errno == 0) \ - errno = ERANGE; \ - } \ - else if (errno == ERANGE) \ - errno = 0; \ - } while(0) - -/* The functions _Py_dg_strtod and _Py_dg_dtoa in Python/dtoa.c (which are - * required to support the short float repr introduced in Python 3.1) require - * that the floating-point unit that's being used for arithmetic operations - * on C doubles is set to use 53-bit precision. It also requires that the - * FPU rounding mode is round-half-to-even, but that's less often an issue. - * - * If your FPU isn't already set to 53-bit precision/round-half-to-even, and - * you want to make use of _Py_dg_strtod and _Py_dg_dtoa, then you should - * - * #define HAVE_PY_SET_53BIT_PRECISION 1 - * - * and also give appropriate definitions for the following three macros: - * - * _PY_SET_53BIT_PRECISION_START : store original FPU settings, and - * set FPU to 53-bit precision/round-half-to-even - * _PY_SET_53BIT_PRECISION_END : restore original FPU settings - * _PY_SET_53BIT_PRECISION_HEADER : any variable declarations needed to - * use the two macros above. - * - * The macros are designed to be used within a single C function: see - * Python/pystrtod.c for an example of their use. - */ - -/* get and set x87 control word for gcc/x86 */ -#ifdef HAVE_GCC_ASM_FOR_X87 -#define HAVE_PY_SET_53BIT_PRECISION 1 -/* _Py_get/set_387controlword functions are defined in Python/pymath.c */ -#define _Py_SET_53BIT_PRECISION_HEADER \ - unsigned short old_387controlword, new_387controlword -#define _Py_SET_53BIT_PRECISION_START \ - do { \ - old_387controlword = _Py_get_387controlword(); \ - new_387controlword = (old_387controlword & ~0x0f00) | 0x0200; \ - if (new_387controlword != old_387controlword) \ - _Py_set_387controlword(new_387controlword); \ - } while (0) -#define _Py_SET_53BIT_PRECISION_END \ - if (new_387controlword != old_387controlword) \ - _Py_set_387controlword(old_387controlword) -#endif - -/* get and set x87 control word for VisualStudio/x86 */ -#if defined(_MSC_VER) && !defined(_WIN64) && !defined(_M_ARM) /* x87 not supported in 64-bit or ARM */ -#define HAVE_PY_SET_53BIT_PRECISION 1 -#define _Py_SET_53BIT_PRECISION_HEADER \ - unsigned int old_387controlword, new_387controlword, out_387controlword -/* We use the __control87_2 function to set only the x87 control word. - The SSE control word is unaffected. */ -#define _Py_SET_53BIT_PRECISION_START \ - do { \ - __control87_2(0, 0, &old_387controlword, NULL); \ - new_387controlword = \ - (old_387controlword & ~(_MCW_PC | _MCW_RC)) | (_PC_53 | _RC_NEAR); \ - if (new_387controlword != old_387controlword) \ - __control87_2(new_387controlword, _MCW_PC | _MCW_RC, \ - &out_387controlword, NULL); \ - } while (0) -#define _Py_SET_53BIT_PRECISION_END \ - do { \ - if (new_387controlword != old_387controlword) \ - __control87_2(old_387controlword, _MCW_PC | _MCW_RC, \ - &out_387controlword, NULL); \ - } while (0) -#endif - -#ifdef HAVE_GCC_ASM_FOR_MC68881 -#define HAVE_PY_SET_53BIT_PRECISION 1 -#define _Py_SET_53BIT_PRECISION_HEADER \ - unsigned int old_fpcr, new_fpcr -#define _Py_SET_53BIT_PRECISION_START \ - do { \ - __asm__ ("fmove.l %%fpcr,%0" : "=g" (old_fpcr)); \ - /* Set double precision / round to nearest. */ \ - new_fpcr = (old_fpcr & ~0xf0) | 0x80; \ - if (new_fpcr != old_fpcr) \ - __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (new_fpcr)); \ - } while (0) -#define _Py_SET_53BIT_PRECISION_END \ - do { \ - if (new_fpcr != old_fpcr) \ - __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (old_fpcr)); \ - } while (0) -#endif - -/* default definitions are empty */ -#ifndef HAVE_PY_SET_53BIT_PRECISION -#define _Py_SET_53BIT_PRECISION_HEADER -#define _Py_SET_53BIT_PRECISION_START -#define _Py_SET_53BIT_PRECISION_END -#endif - -/* If we can't guarantee 53-bit precision, don't use the code - in Python/dtoa.c, but fall back to standard code. This - means that repr of a float will be long (17 sig digits). - - Realistically, there are two things that could go wrong: - - (1) doubles aren't IEEE 754 doubles, or - (2) we're on x86 with the rounding precision set to 64-bits - (extended precision), and we don't know how to change - the rounding precision. - */ - -#if !defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) && \ - !defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) && \ - !defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754) -#define PY_NO_SHORT_FLOAT_REPR -#endif - -/* double rounding is symptomatic of use of extended precision on x86. If - we're seeing double rounding, and we don't have any mechanism available for - changing the FPU rounding precision, then don't use Python/dtoa.c. */ -#if defined(X87_DOUBLE_ROUNDING) && !defined(HAVE_PY_SET_53BIT_PRECISION) -#define PY_NO_SHORT_FLOAT_REPR +# define Py_SAFE_DOWNCAST(VALUE, WIDE, NARROW) _Py_STATIC_CAST(NARROW, (VALUE)) #endif @@ -561,19 +384,51 @@ extern "C" { #define _Py_HOT_FUNCTION #endif -/* _Py_NO_INLINE - * Disable inlining on a function. For example, it helps to reduce the C stack - * consumption. - * - * Usage: - * int _Py_NO_INLINE x(void) { return 3; } - */ -#if defined(_MSC_VER) -# define _Py_NO_INLINE __declspec(noinline) -#elif defined(__GNUC__) || defined(__clang__) -# define _Py_NO_INLINE __attribute__ ((noinline)) +// Ask the compiler to always inline a static inline function. The compiler can +// ignore it and decides to not inline the function. +// +// It can be used to inline performance critical static inline functions when +// building Python in debug mode with function inlining disabled. For example, +// MSC disables function inlining when building in debug mode. +// +// Marking blindly a static inline function with Py_ALWAYS_INLINE can result in +// worse performances (due to increased code size for example). The compiler is +// usually smarter than the developer for the cost/benefit analysis. +// +// If Python is built in debug mode (if the Py_DEBUG macro is defined), the +// Py_ALWAYS_INLINE macro does nothing. +// +// It must be specified before the function return type. Usage: +// +// static inline Py_ALWAYS_INLINE int random(void) { return 4; } +#if defined(Py_DEBUG) + // If Python is built in debug mode, usually compiler optimizations are + // disabled. In this case, Py_ALWAYS_INLINE can increase a lot the stack + // memory usage. For example, forcing inlining using gcc -O0 increases the + // stack usage from 6 KB to 15 KB per Python function call. +# define Py_ALWAYS_INLINE +#elif defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) +# define Py_ALWAYS_INLINE __attribute__((always_inline)) +#elif defined(_MSC_VER) +# define Py_ALWAYS_INLINE __forceinline +#else +# define Py_ALWAYS_INLINE +#endif + +// Py_NO_INLINE +// Disable inlining on a function. For example, it reduces the C stack +// consumption: useful on LTO+PGO builds which heavily inline code (see +// bpo-33720). +// +// Usage: +// +// Py_NO_INLINE static int random(void) { return 4; } +#if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) +# define Py_NO_INLINE __attribute__ ((noinline)) +#elif defined(_MSC_VER) +# define Py_NO_INLINE __declspec(noinline) #else -# define _Py_NO_INLINE +# define Py_NO_INLINE #endif /************************************************************************** @@ -800,26 +655,6 @@ extern char * _getpty(int *, int, mode_t, int); # define PY_LITTLE_ENDIAN 1 #endif -#ifdef Py_BUILD_CORE -/* - * Macros to protect CRT calls against instant termination when passed an - * invalid parameter (issue23524). - */ -#if defined _MSC_VER && _MSC_VER >= 1900 - -extern _invalid_parameter_handler _Py_silent_invalid_parameter_handler; -#define _Py_BEGIN_SUPPRESS_IPH { _invalid_parameter_handler _Py_old_handler = \ - _set_thread_local_invalid_parameter_handler(_Py_silent_invalid_parameter_handler); -#define _Py_END_SUPPRESS_IPH _set_thread_local_invalid_parameter_handler(_Py_old_handler); } - -#else - -#define _Py_BEGIN_SUPPRESS_IPH -#define _Py_END_SUPPRESS_IPH - -#endif /* _MSC_VER >= 1900 */ -#endif /* Py_BUILD_CORE */ - #ifdef __ANDROID__ /* The Android langinfo.h header is not used. */ # undef HAVE_LANGINFO_H @@ -886,4 +721,22 @@ extern _invalid_parameter_handler _Py_silent_invalid_parameter_handler; #endif +/* A convenient way for code to know if sanitizers are enabled. */ +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# if !defined(_Py_MEMORY_SANITIZER) +# define _Py_MEMORY_SANITIZER +# endif +# endif +# if __has_feature(address_sanitizer) +# if !defined(_Py_ADDRESS_SANITIZER) +# define _Py_ADDRESS_SANITIZER +# endif +# endif +#elif defined(__GNUC__) +# if defined(__SANITIZE_ADDRESS__) +# define _Py_ADDRESS_SANITIZER +# endif +#endif + #endif /* Py_PYPORT_H */ diff --git a/include/pystate.h b/include/pystate.h index bae44077..e6b4de97 100644 --- a/include/pystate.h +++ b/include/pystate.h @@ -11,16 +11,6 @@ extern "C" { removed (with effort). */ #define MAX_CO_EXTRA_USERS 255 -/* Forward declarations for PyFrameObject, PyThreadState - and PyInterpreterState */ -struct _ts; -struct _is; - -/* struct _ts is defined in cpython/pystate.h */ -typedef struct _ts PyThreadState; -/* struct _is is defined in internal/pycore_interp.h */ -typedef struct _is PyInterpreterState; - PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_New(void); PyAPI_FUNC(void) PyInterpreterState_Clear(PyInterpreterState *); PyAPI_FUNC(void) PyInterpreterState_Delete(PyInterpreterState *); @@ -50,10 +40,10 @@ PyAPI_FUNC(int64_t) PyInterpreterState_GetID(PyInterpreterState *); /* State unique per thread */ /* New in 3.3 */ -PyAPI_FUNC(int) PyState_AddModule(PyObject*, struct PyModuleDef*); -PyAPI_FUNC(int) PyState_RemoveModule(struct PyModuleDef*); +PyAPI_FUNC(int) PyState_AddModule(PyObject*, PyModuleDef*); +PyAPI_FUNC(int) PyState_RemoveModule(PyModuleDef*); #endif -PyAPI_FUNC(PyObject*) PyState_FindModule(struct PyModuleDef*); +PyAPI_FUNC(PyObject*) PyState_FindModule(PyModuleDef*); PyAPI_FUNC(PyThreadState *) PyThreadState_New(PyInterpreterState *); PyAPI_FUNC(void) PyThreadState_Clear(PyThreadState *); @@ -66,18 +56,10 @@ PyAPI_FUNC(void) PyThreadState_Delete(PyThreadState *); The caller must hold the GIL. - See also PyThreadState_GET() and _PyThreadState_GET(). */ + See also _PyThreadState_UncheckedGet() and _PyThreadState_GET(). */ PyAPI_FUNC(PyThreadState *) PyThreadState_Get(void); -/* Get the current Python thread state. - - Macro using PyThreadState_Get() or _PyThreadState_GET() depending if - pycore_pystate.h is included or not (this header redefines the macro). - - If PyThreadState_Get() is used, issue a fatal error if the current thread - state is NULL. - - See also PyThreadState_Get() and _PyThreadState_GET(). */ +// Alias to PyThreadState_Get() #define PyThreadState_GET() PyThreadState_Get() PyAPI_FUNC(PyThreadState *) PyThreadState_Swap(PyThreadState *); @@ -140,7 +122,7 @@ PyAPI_FUNC(PyThreadState *) PyGILState_GetThisThreadState(void); #ifndef Py_LIMITED_API # define Py_CPYTHON_PYSTATE_H -# include "cpython/pystate.h" +# include "cpython/pystate.h" # undef Py_CPYTHON_PYSTATE_H #endif diff --git a/include/pystrhex.h b/include/pystrhex.h deleted file mode 100644 index a4f36305..00000000 --- a/include/pystrhex.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef Py_STRHEX_H -#define Py_STRHEX_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef Py_LIMITED_API -/* Returns a str() containing the hex representation of argbuf. */ -PyAPI_FUNC(PyObject*) _Py_strhex(const char* argbuf, const Py_ssize_t arglen); -/* Returns a bytes() containing the ASCII hex representation of argbuf. */ -PyAPI_FUNC(PyObject*) _Py_strhex_bytes(const char* argbuf, const Py_ssize_t arglen); -/* These variants include support for a separator between every N bytes: */ -PyAPI_FUNC(PyObject*) _Py_strhex_with_sep(const char* argbuf, const Py_ssize_t arglen, const PyObject* sep, const int bytes_per_group); -PyAPI_FUNC(PyObject*) _Py_strhex_bytes_with_sep(const char* argbuf, const Py_ssize_t arglen, const PyObject* sep, const int bytes_per_group); -#endif /* !Py_LIMITED_API */ - -#ifdef __cplusplus -} -#endif - -#endif /* !Py_STRHEX_H */ diff --git a/include/pystrtod.h b/include/pystrtod.h index c1e84de6..fa056d17 100644 --- a/include/pystrtod.h +++ b/include/pystrtod.h @@ -32,6 +32,7 @@ PyAPI_FUNC(double) _Py_parse_inf_or_nan(const char *p, char **endptr); #define Py_DTSF_ADD_DOT_0 0x02 /* if the result is an integer add ".0" */ #define Py_DTSF_ALT 0x04 /* "alternate" formatting. it's format_code specific */ +#define Py_DTSF_NO_NEG_0 0x08 /* negative zero result is coerced to 0 */ /* PyOS_double_to_string's "type", if non-NULL, will be set to one of: */ #define Py_DTST_FINITE 0 diff --git a/include/pythonrun.h b/include/pythonrun.h index b0a2fc30..1b208b73 100644 --- a/include/pythonrun.h +++ b/include/pythonrun.h @@ -24,6 +24,7 @@ PyAPI_DATA(int) (*PyOS_InputHook)(void); #if defined(WIN32) && !defined(MS_WIN64) && !defined(_M_ARM) && defined(_MSC_VER) && _MSC_VER >= 1300 /* Enable stack checking under Microsoft C */ +// When changing the platforms, ensure PyOS_CheckStack() docs are still correct #define USE_STACKCHECK #endif @@ -34,7 +35,7 @@ PyAPI_FUNC(int) PyOS_CheckStack(void); #ifndef Py_LIMITED_API # define Py_CPYTHON_PYTHONRUN_H -# include "cpython/pythonrun.h" +# include "cpython/pythonrun.h" # undef Py_CPYTHON_PYTHONRUN_H #endif diff --git a/include/pythread.h b/include/pythread.h index bb9d8641..a4832908 100644 --- a/include/pythread.h +++ b/include/pythread.h @@ -1,4 +1,3 @@ - #ifndef Py_PYTHREAD_H #define Py_PYTHREAD_H @@ -16,10 +15,6 @@ typedef enum PyLockStatus { PY_LOCK_INTR } PyLockStatus; -#ifndef Py_LIMITED_API -#define PYTHREAD_INVALID_THREAD_ID ((unsigned long)-1) -#endif - PyAPI_FUNC(void) PyThread_init_thread(void); PyAPI_FUNC(unsigned long) PyThread_start_new_thread(void (*)(void *), void *); PyAPI_FUNC(void) _Py_NO_RETURN PyThread_exit_thread(void); @@ -36,15 +31,6 @@ PyAPI_FUNC(int) PyThread_acquire_lock(PyThread_type_lock, int); #define WAIT_LOCK 1 #define NOWAIT_LOCK 0 -#ifndef Py_LIMITED_API -#ifdef HAVE_FORK -/* Private function to reinitialize a lock at fork in the child process. - Reset the lock to the unlocked state. - Return 0 on success, return -1 on error. */ -PyAPI_FUNC(int) _PyThread_at_fork_reinit(PyThread_type_lock *lock); -#endif /* HAVE_FORK */ -#endif /* !Py_LIMITED_API */ - /* PY_TIMEOUT_T is the integral type used to specify timeouts when waiting on a lock (see PyThread_acquire_lock_timed() below). PY_TIMEOUT_MAX is the highest usable value (in microseconds) of that @@ -61,9 +47,11 @@ PyAPI_FUNC(int) _PyThread_at_fork_reinit(PyThread_type_lock *lock); convert microseconds to nanoseconds. */ # define PY_TIMEOUT_MAX (LLONG_MAX / 1000) #elif defined (NT_THREADS) - /* In the NT API, the timeout is a DWORD and is expressed in milliseconds */ -# if 0xFFFFFFFFLL * 1000 < LLONG_MAX -# define PY_TIMEOUT_MAX (0xFFFFFFFFLL * 1000) + // WaitForSingleObject() accepts timeout in milliseconds in the range + // [0; 0xFFFFFFFE] (DWORD type). INFINITE value (0xFFFFFFFF) means no + // timeout. 0xFFFFFFFE milliseconds is around 49.7 days. +# if 0xFFFFFFFELL * 1000 < LLONG_MAX +# define PY_TIMEOUT_MAX (0xFFFFFFFELL * 1000) # else # define PY_TIMEOUT_MAX LLONG_MAX # endif @@ -122,35 +110,6 @@ Py_DEPRECATED(3.7) PyAPI_FUNC(void) PyThread_ReInitTLS(void); typedef struct _Py_tss_t Py_tss_t; /* opaque */ -#ifndef Py_LIMITED_API -#if defined(_POSIX_THREADS) - /* Darwin needs pthread.h to know type name the pthread_key_t. */ -# include -# define NATIVE_TSS_KEY_T pthread_key_t -#elif defined(NT_THREADS) - /* In Windows, native TSS key type is DWORD, - but hardcode the unsigned long to avoid errors for include directive. - */ -# define NATIVE_TSS_KEY_T unsigned long -#else -# error "Require native threads. See https://bugs.python.org/issue31370" -#endif - -/* When Py_LIMITED_API is not defined, the type layout of Py_tss_t is - exposed to allow static allocation in the API clients. Even in this case, - you must handle TSS keys through API functions due to compatibility. -*/ -struct _Py_tss_t { - int _is_initialized; - NATIVE_TSS_KEY_T _key; -}; - -#undef NATIVE_TSS_KEY_T - -/* When static allocation, you must initialize with Py_tss_NEEDS_INIT. */ -#define Py_tss_NEEDS_INIT {0} -#endif /* !Py_LIMITED_API */ - PyAPI_FUNC(Py_tss_t *) PyThread_tss_alloc(void); PyAPI_FUNC(void) PyThread_tss_free(Py_tss_t *key); @@ -162,8 +121,13 @@ PyAPI_FUNC(int) PyThread_tss_set(Py_tss_t *key, void *value); PyAPI_FUNC(void *) PyThread_tss_get(Py_tss_t *key); #endif /* New in 3.7 */ +#ifndef Py_LIMITED_API +# define Py_CPYTHON_PYTHREAD_H +# include "cpython/pythread.h" +# undef Py_CPYTHON_PYTHREAD_H +#endif + #ifdef __cplusplus } #endif - #endif /* !Py_PYTHREAD_H */ diff --git a/include/pytypedefs.h b/include/pytypedefs.h new file mode 100644 index 00000000..e78ed56a --- /dev/null +++ b/include/pytypedefs.h @@ -0,0 +1,30 @@ +// Forward declarations of types of the Python C API. +// Declare them at the same place since redefining typedef is a C11 feature. +// Only use a forward declaration if there is an interdependency between two +// header files. + +#ifndef Py_PYTYPEDEFS_H +#define Py_PYTYPEDEFS_H +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct PyModuleDef PyModuleDef; +typedef struct PyModuleDef_Slot PyModuleDef_Slot; +typedef struct PyMethodDef PyMethodDef; +typedef struct PyGetSetDef PyGetSetDef; +typedef struct PyMemberDef PyMemberDef; + +typedef struct _object PyObject; +typedef struct _longobject PyLongObject; +typedef struct _typeobject PyTypeObject; +typedef struct PyCodeObject PyCodeObject; +typedef struct _frame PyFrameObject; + +typedef struct _ts PyThreadState; +typedef struct _is PyInterpreterState; + +#ifdef __cplusplus +} +#endif +#endif // !Py_PYTYPEDEFS_H diff --git a/include/setobject.h b/include/setobject.h index 62516be5..fdad7064 100644 --- a/include/setobject.h +++ b/include/setobject.h @@ -6,73 +6,6 @@ extern "C" { #endif -#ifndef Py_LIMITED_API - -/* There are three kinds of entries in the table: - -1. Unused: key == NULL and hash == 0 -2. Dummy: key == dummy and hash == -1 -3. Active: key != NULL and key != dummy and hash != -1 - -The hash field of Unused slots is always zero. - -The hash field of Dummy slots are set to -1 -meaning that dummy entries can be detected by -either entry->key==dummy or by entry->hash==-1. -*/ - -#define PySet_MINSIZE 8 - -typedef struct { - PyObject *key; - Py_hash_t hash; /* Cached hash code of the key */ -} setentry; - -/* The SetObject data structure is shared by set and frozenset objects. - -Invariant for sets: - - hash is -1 - -Invariants for frozensets: - - data is immutable. - - hash is the hash of the frozenset or -1 if not computed yet. - -*/ - -typedef struct { - PyObject_HEAD - - Py_ssize_t fill; /* Number active and dummy entries*/ - Py_ssize_t used; /* Number active entries */ - - /* The table contains mask + 1 slots, and that's a power of 2. - * We store the mask instead of the size because the mask is more - * frequently needed. - */ - Py_ssize_t mask; - - /* The table points to a fixed-size smalltable for small tables - * or to additional malloc'ed memory for bigger tables. - * The table pointer is never NULL which saves us from repeated - * runtime null-tests. - */ - setentry *table; - Py_hash_t hash; /* Only used by frozenset objects */ - Py_ssize_t finger; /* Search finger for pop() */ - - setentry smalltable[PySet_MINSIZE]; - PyObject *weakreflist; /* List of weak references */ -} PySetObject; - -#define PySet_GET_SIZE(so) (assert(PyAnySet_Check(so)),(((PySetObject *)(so))->used)) - -PyAPI_DATA(PyObject *) _PySet_Dummy; - -PyAPI_FUNC(int) _PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash); -PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable); - -#endif /* Section excluded by Py_LIMITED_API */ - PyAPI_DATA(PyTypeObject) PySet_Type; PyAPI_DATA(PyTypeObject) PyFrozenSet_Type; PyAPI_DATA(PyTypeObject) PySetIter_Type; @@ -104,6 +37,12 @@ PyAPI_FUNC(Py_ssize_t) PySet_Size(PyObject *anyset); (Py_IS_TYPE(ob, &PySet_Type) || \ PyType_IsSubtype(Py_TYPE(ob), &PySet_Type)) +#ifndef Py_LIMITED_API +# define Py_CPYTHON_SETOBJECT_H +# include "cpython/setobject.h" +# undef Py_CPYTHON_SETOBJECT_H +#endif + #ifdef __cplusplus } #endif diff --git a/include/structmember.h b/include/structmember.h index 93b7aff8..65a777d5 100644 --- a/include/structmember.h +++ b/include/structmember.h @@ -15,13 +15,13 @@ extern "C" { flag is set). The array must be terminated with an entry whose name pointer is NULL. */ -typedef struct PyMemberDef { +struct PyMemberDef { const char *name; int type; Py_ssize_t offset; int flags; const char *doc; -} PyMemberDef; +}; /* Types */ #define T_SHORT 0 @@ -65,8 +65,8 @@ typedef struct PyMemberDef { #define PY_AUDIT_READ READ_RESTRICTED /* Current API, use this */ -PyAPI_FUNC(PyObject *) PyMember_GetOne(const char *, struct PyMemberDef *); -PyAPI_FUNC(int) PyMember_SetOne(char *, struct PyMemberDef *, PyObject *); +PyAPI_FUNC(PyObject *) PyMember_GetOne(const char *, PyMemberDef *); +PyAPI_FUNC(int) PyMember_SetOne(char *, PyMemberDef *, PyObject *); #ifdef __cplusplus diff --git a/include/structseq.h b/include/structseq.h index 8f51c891..4f5c09f7 100644 --- a/include/structseq.h +++ b/include/structseq.h @@ -15,11 +15,11 @@ typedef struct PyStructSequence_Field { typedef struct PyStructSequence_Desc { const char *name; const char *doc; - struct PyStructSequence_Field *fields; + PyStructSequence_Field *fields; int n_in_sequence; } PyStructSequence_Desc; -extern const char * const PyStructSequence_UnnamedField; +PyAPI_DATA(const char * const) PyStructSequence_UnnamedField; #ifndef Py_LIMITED_API PyAPI_FUNC(void) PyStructSequence_InitType(PyTypeObject *type, diff --git a/include/sysmodule.h b/include/sysmodule.h index 670e5d28..b5087119 100644 --- a/include/sysmodule.h +++ b/include/sysmodule.h @@ -10,9 +10,9 @@ extern "C" { PyAPI_FUNC(PyObject *) PySys_GetObject(const char *); PyAPI_FUNC(int) PySys_SetObject(const char *, PyObject *); -PyAPI_FUNC(void) PySys_SetArgv(int, wchar_t **); -PyAPI_FUNC(void) PySys_SetArgvEx(int, wchar_t **, int); -PyAPI_FUNC(void) PySys_SetPath(const wchar_t *); +Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_SetArgv(int, wchar_t **); +Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_SetArgvEx(int, wchar_t **, int); +Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_SetPath(const wchar_t *); PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...) Py_GCC_ATTRIBUTE((format(printf, 1, 2))); @@ -22,16 +22,16 @@ PyAPI_FUNC(void) PySys_FormatStdout(const char *format, ...); PyAPI_FUNC(void) PySys_FormatStderr(const char *format, ...); PyAPI_FUNC(void) PySys_ResetWarnOptions(void); -PyAPI_FUNC(void) PySys_AddWarnOption(const wchar_t *); -PyAPI_FUNC(void) PySys_AddWarnOptionUnicode(PyObject *); -PyAPI_FUNC(int) PySys_HasWarnOptions(void); +Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_AddWarnOption(const wchar_t *); +Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_AddWarnOptionUnicode(PyObject *); +Py_DEPRECATED(3.11) PyAPI_FUNC(int) PySys_HasWarnOptions(void); -PyAPI_FUNC(void) PySys_AddXOption(const wchar_t *); +Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_AddXOption(const wchar_t *); PyAPI_FUNC(PyObject *) PySys_GetXOptions(void); #ifndef Py_LIMITED_API # define Py_CPYTHON_SYSMODULE_H -# include "cpython/sysmodule.h" +# include "cpython/sysmodule.h" # undef Py_CPYTHON_SYSMODULE_H #endif diff --git a/include/traceback.h b/include/traceback.h index 781e5a6e..2dfa2ada 100644 --- a/include/traceback.h +++ b/include/traceback.h @@ -16,7 +16,7 @@ PyAPI_DATA(PyTypeObject) PyTraceBack_Type; #ifndef Py_LIMITED_API # define Py_CPYTHON_TRACEBACK_H -# include "cpython/traceback.h" +# include "cpython/traceback.h" # undef Py_CPYTHON_TRACEBACK_H #endif diff --git a/include/tupleobject.h b/include/tupleobject.h index e796a320..dc68e3fc 100644 --- a/include/tupleobject.h +++ b/include/tupleobject.h @@ -36,7 +36,7 @@ PyAPI_FUNC(PyObject *) PyTuple_Pack(Py_ssize_t, ...); #ifndef Py_LIMITED_API # define Py_CPYTHON_TUPLEOBJECT_H -# include "cpython/tupleobject.h" +# include "cpython/tupleobject.h" # undef Py_CPYTHON_TUPLEOBJECT_H #endif diff --git a/include/typeslots.h b/include/typeslots.h index 5800d015..506b0558 100644 --- a/include/typeslots.h +++ b/include/typeslots.h @@ -1,12 +1,6 @@ /* Do not renumber the file; these numbers are part of the stable ABI. */ -#if defined(Py_LIMITED_API) -/* Disabled, see #10181 */ -#undef Py_bf_getbuffer -#undef Py_bf_releasebuffer -#else #define Py_bf_getbuffer 1 #define Py_bf_releasebuffer 2 -#endif #define Py_mp_ass_subscript 3 #define Py_mp_length 4 #define Py_mp_subscript 5 diff --git a/include/unicodeobject.h b/include/unicodeobject.h index b0ac086a..1d2f5460 100644 --- a/include/unicodeobject.h +++ b/include/unicodeobject.h @@ -1,7 +1,7 @@ #ifndef Py_UNICODEOBJECT_H #define Py_UNICODEOBJECT_H -#include +#include // va_list /* @@ -112,7 +112,7 @@ PyAPI_DATA(PyTypeObject) PyUnicode_Type; PyAPI_DATA(PyTypeObject) PyUnicodeIter_Type; #define PyUnicode_Check(op) \ - PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_UNICODE_SUBCLASS) + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_UNICODE_SUBCLASS) #define PyUnicode_CheckExact(op) Py_IS_TYPE(op, &PyUnicode_Type) /* --- Constants ---------------------------------------------------------- */ @@ -269,10 +269,6 @@ PyAPI_FUNC(PyObject *) PyUnicode_InternFromString( // and will be removed in Python 3.12. Use PyUnicode_InternInPlace() instead. Py_DEPRECATED(3.10) PyAPI_FUNC(void) PyUnicode_InternImmortal(PyObject **); -/* Use only if you know it's a string */ -#define PyUnicode_CHECK_INTERNED(op) \ - (((PyASCIIObject *)(op))->state.interned) - /* --- wchar_t support for platforms which support it --------------------- */ #ifdef HAVE_WCHAR_H @@ -1043,7 +1039,7 @@ PyAPI_FUNC(int) PyUnicode_IsIdentifier(PyObject *s); #ifndef Py_LIMITED_API # define Py_CPYTHON_UNICODEOBJECT_H -# include "cpython/unicodeobject.h" +# include "cpython/unicodeobject.h" # undef Py_CPYTHON_UNICODEOBJECT_H #endif diff --git a/include/warnings.h b/include/warnings.h index a675bb5d..18ac1543 100644 --- a/include/warnings.h +++ b/include/warnings.h @@ -4,14 +4,11 @@ extern "C" { #endif -#ifndef Py_LIMITED_API -PyAPI_FUNC(PyObject*) _PyWarnings_Init(void); -#endif - PyAPI_FUNC(int) PyErr_WarnEx( PyObject *category, const char *message, /* UTF-8 encoded string */ Py_ssize_t stack_level); + PyAPI_FUNC(int) PyErr_WarnFormat( PyObject *category, Py_ssize_t stack_level, @@ -26,15 +23,7 @@ PyAPI_FUNC(int) PyErr_ResourceWarning( const char *format, /* ASCII-encoded string */ ...); #endif -#ifndef Py_LIMITED_API -PyAPI_FUNC(int) PyErr_WarnExplicitObject( - PyObject *category, - PyObject *message, - PyObject *filename, - int lineno, - PyObject *module, - PyObject *registry); -#endif + PyAPI_FUNC(int) PyErr_WarnExplicit( PyObject *category, const char *message, /* UTF-8 encoded string */ @@ -44,20 +33,9 @@ PyAPI_FUNC(int) PyErr_WarnExplicit( PyObject *registry); #ifndef Py_LIMITED_API -PyAPI_FUNC(int) -PyErr_WarnExplicitFormat(PyObject *category, - const char *filename, int lineno, - const char *module, PyObject *registry, - const char *format, ...); -#endif - -/* DEPRECATED: Use PyErr_WarnEx() instead. */ -#ifndef Py_LIMITED_API -#define PyErr_Warn(category, msg) PyErr_WarnEx(category, msg, 1) -#endif - -#ifndef Py_LIMITED_API -void _PyErr_WarnUnawaitedCoroutine(PyObject *coro); +# define Py_CPYTHON_WARNINGS_H +# include "cpython/warnings.h" +# undef Py_CPYTHON_WARNINGS_H #endif #ifdef __cplusplus diff --git a/include/weakrefobject.h b/include/weakrefobject.h index ac4b4821..f071e9c7 100644 --- a/include/weakrefobject.h +++ b/include/weakrefobject.h @@ -6,40 +6,8 @@ extern "C" { #endif - typedef struct _PyWeakReference PyWeakReference; -/* PyWeakReference is the base struct for the Python ReferenceType, ProxyType, - * and CallableProxyType. - */ -#ifndef Py_LIMITED_API -struct _PyWeakReference { - PyObject_HEAD - - /* The object to which this is a weak reference, or Py_None if none. - * Note that this is a stealth reference: wr_object's refcount is - * not incremented to reflect this pointer. - */ - PyObject *wr_object; - - /* A callable to invoke when wr_object dies, or NULL if none. */ - PyObject *wr_callback; - - /* A cache for wr_object's hash code. As usual for hashes, this is -1 - * if the hash code isn't known yet. - */ - Py_hash_t hash; - - /* If wr_object is weakly referenced, wr_object has a doubly-linked NULL- - * terminated list of weak references to it. These are the list pointers. - * If wr_object goes away, wr_object is set to Py_None, and these pointers - * have no meaning then. - */ - PyWeakReference *wr_prev; - PyWeakReference *wr_next; -}; -#endif - PyAPI_DATA(PyTypeObject) _PyWeakref_RefType; PyAPI_DATA(PyTypeObject) _PyWeakref_ProxyType; PyAPI_DATA(PyTypeObject) _PyWeakref_CallableProxyType; @@ -56,30 +24,18 @@ PyAPI_DATA(PyTypeObject) _PyWeakref_CallableProxyType; PyAPI_FUNC(PyObject *) PyWeakref_NewRef(PyObject *ob, - PyObject *callback); + PyObject *callback); PyAPI_FUNC(PyObject *) PyWeakref_NewProxy(PyObject *ob, - PyObject *callback); + PyObject *callback); PyAPI_FUNC(PyObject *) PyWeakref_GetObject(PyObject *ref); -#ifndef Py_LIMITED_API -PyAPI_FUNC(Py_ssize_t) _PyWeakref_GetWeakrefCount(PyWeakReference *head); -PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference *self); +#ifndef Py_LIMITED_API +# define Py_CPYTHON_WEAKREFOBJECT_H +# include "cpython/weakrefobject.h" +# undef Py_CPYTHON_WEAKREFOBJECT_H #endif -/* Explanation for the Py_REFCNT() check: when a weakref's target is part - of a long chain of deallocations which triggers the trashcan mechanism, - clearing the weakrefs can be delayed long after the target's refcount - has dropped to zero. In the meantime, code accessing the weakref will - be able to "see" the target object even though it is supposed to be - unreachable. See issue #16602. */ - -#define PyWeakref_GET_OBJECT(ref) \ - (Py_REFCNT(((PyWeakReference *)(ref))->wr_object) > 0 \ - ? ((PyWeakReference *)(ref))->wr_object \ - : Py_None) - - #ifdef __cplusplus } #endif diff --git a/lib/python310.lib b/lib/python310.lib deleted file mode 100644 index c4a29012..00000000 Binary files a/lib/python310.lib and /dev/null differ diff --git a/lib/python311.lib b/lib/python311.lib new file mode 100644 index 00000000..2e8fc31b Binary files /dev/null and b/lib/python311.lib differ diff --git a/src/api/utils.cpp b/src/api/utils.cpp index c8b550bd..4b6b13ad 100644 --- a/src/api/utils.cpp +++ b/src/api/utils.cpp @@ -21,10 +21,10 @@ namespace mc { void setListener(const string& event_name, const py::function& cb) { auto event_code = magic_enum::enum_cast(event_name); if (!event_code) throw py::value_error("Invalid event name " + event_name); - //濡傛灉鐩戝惉鍣ㄦ湭鍚敤锛屽垯鍚敤 + // 濡傛灉鐩戝惉鍣ㄦ湭鍚敤锛屽垯鍚敤 if (listeners.find(event_code.value()) == listeners.end()) EnableEventListener(event_code.value()); - //娣诲姞鍥炶皟鍑芥暟 + // 娣诲姞鍥炶皟鍑芥暟 listeners[event_code.value()].push_back(cb); } @@ -86,7 +86,7 @@ NBTClass getStructure(const BlockPos& pos1, const BlockPos& pos2, int dim, bool ignore_entities, bool ignore_blocks) { auto st = StructureTemplate::fromWorld("name", dim, pos1, pos2, ignore_entities, ignore_blocks); - return st.save(); + return st->save(); // TODO: check memory leak } bool setStructure(const NBTClass& nbt, const BlockPos& pos, int dim, Mirror mir, @@ -100,7 +100,7 @@ bool setStructure(const NBTClass& nbt, const BlockPos& pos, int dim, Mirror mir, } } }*/ - return st.toWorld(dim, pos, mir, rot); + return st->toWorld(dim, pos, mir, rot); // TODO: check memory leak } void explode(const Vec3& pos, int dim, float power, bool destroy, float range, diff --git a/src/main.cpp b/src/main.cpp index caac0093..ed3de97d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,8 +7,8 @@ constexpr unsigned PYR_VERSION_MAJOR = 2; constexpr unsigned PYR_VERSION_MINOR = 1; -constexpr unsigned PYR_VERSION_MICRO = 2; -constexpr const char* PYR_VERSION = "v2.1.2"; +constexpr unsigned PYR_VERSION_MICRO = 3; +constexpr const char* PYR_VERSION = "v2.1.3"; Logger logger("BDSpyrunner");