| 
									
										
										
										
											2019-06-03 21:30:58 +09:00
										 |  |  | #ifndef Py_INTERNAL_CODE_H
 | 
					
						
							|  |  |  | #define Py_INTERNAL_CODE_H
 | 
					
						
							|  |  |  | #ifdef __cplusplus
 | 
					
						
							|  |  |  | extern "C" { | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-05-27 09:54:34 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 09:28:27 -08:00
										 |  |  | #define CODE_MAX_WATCHERS 8
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 18:38:06 +01:00
										 |  |  | /* PEP 659
 | 
					
						
							|  |  |  |  * Specialization and quickening structs and helper functions | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-07 11:45:00 -08:00
										 |  |  | // 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!
 | 
					
						
							| 
									
										
										
										
											2022-02-28 12:56:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define CACHE_ENTRIES(cache) (sizeof(cache)/sizeof(_Py_CODEUNIT))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2022-12-14 11:12:53 +00:00
										 |  |  |     uint16_t counter; | 
					
						
							| 
									
										
										
										
											2023-03-10 17:01:16 -08:00
										 |  |  |     uint16_t module_keys_version; | 
					
						
							| 
									
										
										
										
											2022-12-14 11:12:53 +00:00
										 |  |  |     uint16_t builtin_keys_version; | 
					
						
							| 
									
										
										
										
											2023-07-12 14:34:14 +01:00
										 |  |  |     uint16_t index; | 
					
						
							| 
									
										
										
										
											2022-02-28 12:56:29 +00:00
										 |  |  | } _PyLoadGlobalCache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define INLINE_CACHE_ENTRIES_LOAD_GLOBAL CACHE_ENTRIES(_PyLoadGlobalCache)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-25 04:11:34 -08:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2022-12-14 11:12:53 +00:00
										 |  |  |     uint16_t counter; | 
					
						
							| 
									
										
										
										
											2022-02-25 04:11:34 -08:00
										 |  |  | } _PyBinaryOpCache; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-28 12:56:29 +00:00
										 |  |  | #define INLINE_CACHE_ENTRIES_BINARY_OP CACHE_ENTRIES(_PyBinaryOpCache)
 | 
					
						
							| 
									
										
										
										
											2022-03-01 05:53:13 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-28 03:54:14 -08:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2022-12-14 11:12:53 +00:00
										 |  |  |     uint16_t counter; | 
					
						
							| 
									
										
										
										
											2022-02-28 03:54:14 -08:00
										 |  |  | } _PyUnpackSequenceCache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE \
 | 
					
						
							| 
									
										
										
										
											2022-03-01 05:53:13 -08:00
										 |  |  |     CACHE_ENTRIES(_PyUnpackSequenceCache) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2022-12-14 11:12:53 +00:00
										 |  |  |     uint16_t counter; | 
					
						
							| 
									
										
										
										
											2022-03-01 05:53:13 -08:00
										 |  |  | } _PyCompareOpCache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define INLINE_CACHE_ENTRIES_COMPARE_OP CACHE_ENTRIES(_PyCompareOpCache)
 | 
					
						
							| 
									
										
										
										
											2022-02-28 03:54:14 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-01 16:00:34 +00:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2022-12-14 11:12:53 +00:00
										 |  |  |     uint16_t counter; | 
					
						
							| 
									
										
										
										
											2022-03-01 16:00:34 +00:00
										 |  |  | } _PyBinarySubscrCache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define INLINE_CACHE_ENTRIES_BINARY_SUBSCR CACHE_ENTRIES(_PyBinarySubscrCache)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 11:45:51 -06:00
										 |  |  | typedef struct { | 
					
						
							|  |  |  |     uint16_t counter; | 
					
						
							|  |  |  | } _PySuperAttrCache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR CACHE_ENTRIES(_PySuperAttrCache)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-03 15:31:00 -08:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2022-12-14 11:12:53 +00:00
										 |  |  |     uint16_t counter; | 
					
						
							|  |  |  |     uint16_t version[2]; | 
					
						
							|  |  |  |     uint16_t index; | 
					
						
							| 
									
										
										
										
											2022-03-03 15:31:00 -08:00
										 |  |  | } _PyAttrCache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2022-12-14 11:12:53 +00:00
										 |  |  |     uint16_t counter; | 
					
						
							|  |  |  |     uint16_t type_version[2]; | 
					
						
							|  |  |  |     uint16_t keys_version[2]; | 
					
						
							|  |  |  |     uint16_t descr[4]; | 
					
						
							| 
									
										
										
										
											2022-03-03 15:31:00 -08:00
										 |  |  | } _PyLoadMethodCache; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-14 18:36:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // MUST be the max(_PyAttrCache, _PyLoadMethodCache)
 | 
					
						
							|  |  |  | #define INLINE_CACHE_ENTRIES_LOAD_ATTR CACHE_ENTRIES(_PyLoadMethodCache)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define INLINE_CACHE_ENTRIES_STORE_ATTR CACHE_ENTRIES(_PyAttrCache)
 | 
					
						
							| 
									
										
										
										
											2022-03-03 15:31:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-07 11:45:00 -08:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2022-12-14 11:12:53 +00:00
										 |  |  |     uint16_t counter; | 
					
						
							|  |  |  |     uint16_t func_version[2]; | 
					
						
							| 
									
										
										
										
											2022-03-07 11:45:00 -08:00
										 |  |  | } _PyCallCache; | 
					
						
							| 
									
										
										
										
											2021-06-07 18:38:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-07 11:45:00 -08:00
										 |  |  | #define INLINE_CACHE_ENTRIES_CALL CACHE_ENTRIES(_PyCallCache)
 | 
					
						
							| 
									
										
										
										
											2021-06-07 18:38:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 07:53:22 -08:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2022-12-14 11:12:53 +00:00
										 |  |  |     uint16_t counter; | 
					
						
							| 
									
										
										
										
											2022-03-08 07:53:22 -08:00
										 |  |  | } _PyStoreSubscrCache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define INLINE_CACHE_ENTRIES_STORE_SUBSCR CACHE_ENTRIES(_PyStoreSubscrCache)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-21 06:19:26 -04:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2022-12-14 11:12:53 +00:00
										 |  |  |     uint16_t counter; | 
					
						
							| 
									
										
										
										
											2022-06-21 06:19:26 -04:00
										 |  |  | } _PyForIterCache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define INLINE_CACHE_ENTRIES_FOR_ITER CACHE_ENTRIES(_PyForIterCache)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-13 11:24:55 +00:00
										 |  |  | typedef struct { | 
					
						
							|  |  |  |     uint16_t counter; | 
					
						
							|  |  |  | } _PySendCache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define INLINE_CACHE_ENTRIES_SEND CACHE_ENTRIES(_PySendCache)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-29 13:49:54 -07:00
										 |  |  | typedef struct { | 
					
						
							|  |  |  |     uint16_t counter; | 
					
						
							|  |  |  |     uint16_t version[2]; | 
					
						
							|  |  |  | } _PyToBoolCache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define INLINE_CACHE_ENTRIES_TO_BOOL CACHE_ENTRIES(_PyToBoolCache)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-07 11:45:00 -08:00
										 |  |  | // Borrowed references to common callables:
 | 
					
						
							|  |  |  | struct callable_cache { | 
					
						
							|  |  |  |     PyObject *isinstance; | 
					
						
							|  |  |  |     PyObject *len; | 
					
						
							|  |  |  |     PyObject *list_append; | 
					
						
							| 
									
										
										
										
											2022-08-17 19:37:07 +08:00
										 |  |  |     PyObject *object__getattribute__; | 
					
						
							| 
									
										
										
										
											2022-03-07 11:45:00 -08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 12:22:26 -06:00
										 |  |  | /* "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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-21 13:53:04 -07:00
										 |  |  | // Note that these all fit within a byte, as do combinations.
 | 
					
						
							| 
									
										
										
										
											2021-06-07 12:22:26 -06:00
										 |  |  | // Later, we will use the smaller numbers to differentiate the different
 | 
					
						
							|  |  |  | // kinds of locals (e.g. pos-only arg, varkwargs, local-only).
 | 
					
						
							| 
									
										
										
										
											2023-05-09 11:02:14 -06:00
										 |  |  | #define CO_FAST_HIDDEN  0x10
 | 
					
						
							| 
									
										
										
										
											2021-06-07 12:22:26 -06:00
										 |  |  | #define CO_FAST_LOCAL   0x20
 | 
					
						
							|  |  |  | #define CO_FAST_CELL    0x40
 | 
					
						
							|  |  |  | #define CO_FAST_FREE    0x80
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-21 13:53:04 -07:00
										 |  |  | typedef unsigned char _PyLocals_Kind; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline _PyLocals_Kind | 
					
						
							|  |  |  | _PyLocals_GetKind(PyObject *kinds, int i) | 
					
						
							| 
									
										
										
										
											2021-06-07 12:22:26 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-21 13:53:04 -07:00
										 |  |  |     assert(PyBytes_Check(kinds)); | 
					
						
							|  |  |  |     assert(0 <= i && i < PyBytes_GET_SIZE(kinds)); | 
					
						
							|  |  |  |     char *ptr = PyBytes_AS_STRING(kinds); | 
					
						
							|  |  |  |     return (_PyLocals_Kind)(ptr[i]); | 
					
						
							| 
									
										
										
										
											2021-06-07 12:22:26 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void | 
					
						
							| 
									
										
										
										
											2021-06-21 13:53:04 -07:00
										 |  |  | _PyLocals_SetKind(PyObject *kinds, int i, _PyLocals_Kind kind) | 
					
						
							| 
									
										
										
										
											2021-06-07 12:22:26 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-21 13:53:04 -07:00
										 |  |  |     assert(PyBytes_Check(kinds)); | 
					
						
							|  |  |  |     assert(0 <= i && i < PyBytes_GET_SIZE(kinds)); | 
					
						
							|  |  |  |     char *ptr = PyBytes_AS_STRING(kinds); | 
					
						
							|  |  |  |     ptr[i] = (char) kind; | 
					
						
							| 
									
										
										
										
											2021-06-07 12:22:26 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-21 13:53:04 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-27 09:54:34 -06:00
										 |  |  | struct _PyCodeConstructor { | 
					
						
							|  |  |  |     /* metadata */ | 
					
						
							|  |  |  |     PyObject *filename; | 
					
						
							|  |  |  |     PyObject *name; | 
					
						
							| 
									
										
										
										
											2021-07-07 12:21:51 +01:00
										 |  |  |     PyObject *qualname; | 
					
						
							| 
									
										
										
										
											2021-05-27 09:54:34 -06:00
										 |  |  |     int flags; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* the code */ | 
					
						
							|  |  |  |     PyObject *code; | 
					
						
							|  |  |  |     int firstlineno; | 
					
						
							|  |  |  |     PyObject *linetable; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* used by the code */ | 
					
						
							|  |  |  |     PyObject *consts; | 
					
						
							|  |  |  |     PyObject *names; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* mapping frame offsets to information */ | 
					
						
							| 
									
										
										
										
											2021-06-21 13:53:04 -07:00
										 |  |  |     PyObject *localsplusnames;  // Tuple of strings
 | 
					
						
							|  |  |  |     PyObject *localspluskinds;  // Bytes object, one byte per variable
 | 
					
						
							| 
									
										
										
										
											2021-05-27 09:54:34 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* args (within varnames) */ | 
					
						
							|  |  |  |     int argcount; | 
					
						
							|  |  |  |     int posonlyargcount; | 
					
						
							| 
									
										
										
										
											2021-06-07 12:22:26 -06:00
										 |  |  |     // XXX Replace argcount with posorkwargcount (argcount - posonlyargcount).
 | 
					
						
							| 
									
										
										
										
											2021-05-27 09:54:34 -06:00
										 |  |  |     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.)
 | 
					
						
							| 
									
										
										
										
											2023-07-25 03:44:11 +02:00
										 |  |  | extern int _PyCode_Validate(struct _PyCodeConstructor *); | 
					
						
							|  |  |  | extern PyCodeObject* _PyCode_New(struct _PyCodeConstructor *); | 
					
						
							| 
									
										
										
										
											2021-05-27 09:54:34 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-03 21:30:58 +09:00
										 |  |  | /* Private API */ | 
					
						
							| 
									
										
										
										
											2021-05-27 09:54:34 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 12:22:26 -06:00
										 |  |  | /* Getters for internal PyCodeObject data. */ | 
					
						
							| 
									
										
										
										
											2022-02-25 15:41:32 +01:00
										 |  |  | extern PyObject* _PyCode_GetVarnames(PyCodeObject *); | 
					
						
							|  |  |  | extern PyObject* _PyCode_GetCellvars(PyCodeObject *); | 
					
						
							|  |  |  | extern PyObject* _PyCode_GetFreevars(PyCodeObject *); | 
					
						
							| 
									
										
										
										
											2022-03-21 04:11:17 -07:00
										 |  |  | extern PyObject* _PyCode_GetCode(PyCodeObject *); | 
					
						
							| 
									
										
										
										
											2022-02-25 15:41:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** API for initializing the line number tables. */ | 
					
						
							|  |  |  | extern int _PyCode_InitAddressRange(PyCodeObject* co, PyCodeAddressRange *bounds); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-21 16:10:37 +01:00
										 |  |  | /** Out of process API for initializing the location table. */ | 
					
						
							| 
									
										
										
										
											2022-02-25 15:41:32 +01:00
										 |  |  | 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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-10 08:46:01 +01:00
										 |  |  | /* Specialization functions */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-11 08:08:13 -06:00
										 |  |  | extern void _Py_Specialize_LoadSuperAttr(PyObject *global_super, PyObject *cls, | 
					
						
							|  |  |  |                                          _Py_CODEUNIT *instr, int load_method); | 
					
						
							| 
									
										
										
										
											2022-11-17 15:09:18 -08:00
										 |  |  | extern void _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, | 
					
						
							| 
									
										
										
										
											2022-03-03 15:31:00 -08:00
										 |  |  |                                     PyObject *name); | 
					
						
							| 
									
										
										
										
											2022-11-17 15:09:18 -08:00
										 |  |  | extern void _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, | 
					
						
							|  |  |  |                                      PyObject *name); | 
					
						
							| 
									
										
										
										
											2022-11-09 10:50:09 -08:00
										 |  |  | extern void _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, | 
					
						
							|  |  |  |                                       _Py_CODEUNIT *instr, PyObject *name); | 
					
						
							|  |  |  | extern void _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, | 
					
						
							|  |  |  |                                         _Py_CODEUNIT *instr); | 
					
						
							|  |  |  | extern void _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, | 
					
						
							|  |  |  |                                        _Py_CODEUNIT *instr); | 
					
						
							|  |  |  | extern void _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, | 
					
						
							|  |  |  |                                 int nargs, PyObject *kwnames); | 
					
						
							| 
									
										
										
										
											2022-02-25 15:41:32 +01:00
										 |  |  | extern void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, | 
					
						
							| 
									
										
										
										
											2022-03-25 12:13:19 -04:00
										 |  |  |                                     int oparg, PyObject **locals); | 
					
						
							| 
									
										
										
										
											2023-03-23 15:25:09 -07:00
										 |  |  | extern void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, | 
					
						
							| 
									
										
										
										
											2022-03-01 05:53:13 -08:00
										 |  |  |                                      _Py_CODEUNIT *instr, int oparg); | 
					
						
							| 
									
										
										
										
											2022-02-25 15:41:32 +01:00
										 |  |  | extern void _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, | 
					
						
							| 
									
										
										
										
											2022-02-28 03:54:14 -08:00
										 |  |  |                                           int oparg); | 
					
						
							| 
									
										
										
										
											2022-11-07 06:49:51 -08:00
										 |  |  | extern void _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr, int oparg); | 
					
						
							| 
									
										
										
										
											2023-02-13 11:24:55 +00:00
										 |  |  | extern void _Py_Specialize_Send(PyObject *receiver, _Py_CODEUNIT *instr); | 
					
						
							| 
									
										
										
										
											2023-06-29 13:49:54 -07:00
										 |  |  | extern void _Py_Specialize_ToBool(PyObject *value, _Py_CODEUNIT *instr); | 
					
						
							| 
									
										
										
										
											2021-06-10 08:46:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-02 10:42:57 -07:00
										 |  |  | /* Finalizer function for static codeobjects used in deepfreeze.py */ | 
					
						
							|  |  |  | extern void _PyStaticCode_Fini(PyCodeObject *co); | 
					
						
							|  |  |  | /* Function to intern strings of codeobjects and quicken the bytecode */ | 
					
						
							|  |  |  | extern int _PyStaticCode_Init(PyCodeObject *co); | 
					
						
							| 
									
										
										
										
											2021-08-12 12:15:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-15 15:32:32 +00:00
										 |  |  | #ifdef Py_STATS
 | 
					
						
							| 
									
										
										
										
											2021-06-15 13:01:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-17 14:48:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-21 15:40:54 +01:00
										 |  |  | #define STAT_INC(opname, name) do { if (_py_stats) _py_stats->opcode_stats[opname].specialization.name++; } while (0)
 | 
					
						
							|  |  |  | #define STAT_DEC(opname, name) do { if (_py_stats) _py_stats->opcode_stats[opname].specialization.name--; } while (0)
 | 
					
						
							|  |  |  | #define OPCODE_EXE_INC(opname) do { if (_py_stats) _py_stats->opcode_stats[opname].execution_count++; } while (0)
 | 
					
						
							|  |  |  | #define CALL_STAT_INC(name) do { if (_py_stats) _py_stats->call_stats.name++; } while (0)
 | 
					
						
							|  |  |  | #define OBJECT_STAT_INC(name) do { if (_py_stats) _py_stats->object_stats.name++; } while (0)
 | 
					
						
							| 
									
										
										
										
											2022-05-03 16:40:24 -06:00
										 |  |  | #define OBJECT_STAT_INC_COND(name, cond) \
 | 
					
						
							| 
									
										
										
										
											2022-06-21 15:40:54 +01:00
										 |  |  |     do { if (_py_stats && cond) _py_stats->object_stats.name++; } while (0) | 
					
						
							|  |  |  | #define EVAL_CALL_STAT_INC(name) do { if (_py_stats) _py_stats->call_stats.eval_calls[name]++; } while (0)
 | 
					
						
							| 
									
										
										
										
											2022-05-27 16:31:41 +01:00
										 |  |  | #define EVAL_CALL_STAT_INC_IF_FUNCTION(name, callable) \
 | 
					
						
							| 
									
										
										
										
											2022-06-21 15:40:54 +01:00
										 |  |  |     do { if (_py_stats && PyFunction_Check(callable)) _py_stats->call_stats.eval_calls[name]++; } while (0) | 
					
						
							| 
									
										
										
										
											2021-12-17 14:48:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-25 03:44:11 +02:00
										 |  |  | // Export for stdlib '_opcode' shared extension
 | 
					
						
							| 
									
										
										
										
											2022-04-28 14:02:45 +02:00
										 |  |  | PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void); | 
					
						
							| 
									
										
										
										
											2021-07-29 17:26:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-10 08:46:01 +01:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2021-06-14 11:04:09 +01:00
										 |  |  | #define STAT_INC(opname, name) ((void)0)
 | 
					
						
							| 
									
										
										
										
											2021-07-29 20:50:03 +01:00
										 |  |  | #define STAT_DEC(opname, name) ((void)0)
 | 
					
						
							| 
									
										
										
										
											2021-12-17 14:48:01 +00:00
										 |  |  | #define OPCODE_EXE_INC(opname) ((void)0)
 | 
					
						
							| 
									
										
										
										
											2022-01-28 15:20:33 +00:00
										 |  |  | #define CALL_STAT_INC(name) ((void)0)
 | 
					
						
							| 
									
										
										
										
											2022-02-01 15:05:18 +00:00
										 |  |  | #define OBJECT_STAT_INC(name) ((void)0)
 | 
					
						
							| 
									
										
										
										
											2022-05-03 16:40:24 -06:00
										 |  |  | #define OBJECT_STAT_INC_COND(name, cond) ((void)0)
 | 
					
						
							| 
									
										
										
										
											2022-05-27 16:31:41 +01:00
										 |  |  | #define EVAL_CALL_STAT_INC(name) ((void)0)
 | 
					
						
							|  |  |  | #define EVAL_CALL_STAT_INC_IF_FUNCTION(name, callable) ((void)0)
 | 
					
						
							| 
									
										
										
										
											2022-04-28 14:02:45 +02:00
										 |  |  | #endif  // !Py_STATS
 | 
					
						
							| 
									
										
										
										
											2021-06-10 08:46:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-14 17:05:04 -07:00
										 |  |  | // Utility functions for reading/writing 32/64-bit values in the inline caches.
 | 
					
						
							|  |  |  | // Great care should be taken to ensure that these functions remain correct and
 | 
					
						
							|  |  |  | // performant! They should compile to just "move" instructions on all supported
 | 
					
						
							|  |  |  | // compilers and platforms.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // We use memcpy to let the C compiler handle unaligned accesses and endianness
 | 
					
						
							|  |  |  | // issues for us. It also seems to produce better code than manual copying for
 | 
					
						
							|  |  |  | // most compilers (see https://blog.regehr.org/archives/959 for more info).
 | 
					
						
							| 
									
										
										
										
											2022-02-28 12:56:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static inline void | 
					
						
							| 
									
										
										
										
											2022-03-03 15:31:00 -08:00
										 |  |  | write_u32(uint16_t *p, uint32_t val) | 
					
						
							| 
									
										
										
										
											2022-02-28 12:56:29 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-09-14 17:05:04 -07:00
										 |  |  |     memcpy(p, &val, sizeof(val)); | 
					
						
							| 
									
										
										
										
											2022-03-03 15:31:00 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void | 
					
						
							|  |  |  | write_u64(uint16_t *p, uint64_t val) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-09-14 17:05:04 -07:00
										 |  |  |     memcpy(p, &val, sizeof(val)); | 
					
						
							| 
									
										
										
										
											2022-03-03 15:31:00 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void | 
					
						
							| 
									
										
										
										
											2022-09-14 17:05:04 -07:00
										 |  |  | write_obj(uint16_t *p, PyObject *val) | 
					
						
							| 
									
										
										
										
											2022-02-28 12:56:29 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-09-14 17:05:04 -07:00
										 |  |  |     memcpy(p, &val, sizeof(val)); | 
					
						
							| 
									
										
										
										
											2022-02-28 12:56:29 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-22 16:04:57 -08:00
										 |  |  | static inline uint16_t | 
					
						
							|  |  |  | read_u16(uint16_t *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return *p; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-28 12:56:29 +00:00
										 |  |  | static inline uint32_t | 
					
						
							| 
									
										
										
										
											2022-03-03 15:31:00 -08:00
										 |  |  | read_u32(uint16_t *p) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-09-14 17:05:04 -07:00
										 |  |  |     uint32_t val; | 
					
						
							|  |  |  |     memcpy(&val, p, sizeof(val)); | 
					
						
							| 
									
										
										
										
											2022-03-03 15:31:00 -08:00
										 |  |  |     return val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline uint64_t | 
					
						
							|  |  |  | read_u64(uint16_t *p) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-09-14 17:05:04 -07:00
										 |  |  |     uint64_t val; | 
					
						
							|  |  |  |     memcpy(&val, p, sizeof(val)); | 
					
						
							| 
									
										
										
										
											2022-03-03 15:31:00 -08:00
										 |  |  |     return val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline PyObject * | 
					
						
							|  |  |  | read_obj(uint16_t *p) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-09-14 17:05:04 -07:00
										 |  |  |     PyObject *val; | 
					
						
							|  |  |  |     memcpy(&val, p, sizeof(val)); | 
					
						
							|  |  |  |     return val; | 
					
						
							| 
									
										
										
										
											2022-03-03 15:31:00 -08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-06-10 08:46:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-18 16:06:42 +01:00
										 |  |  | /* 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-21 16:10:37 +01:00
										 |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-31 11:58:26 +01:00
										 |  |  | /** 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
 | 
					
						
							| 
									
										
										
										
											2022-11-09 10:50:09 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // A value of 1 means that we attempt to specialize the *second* time each
 | 
					
						
							|  |  |  | // instruction is executed. Executing twice is a much better indicator of
 | 
					
						
							|  |  |  | // "hotness" than executing once, but additional warmup delays only prevent
 | 
					
						
							|  |  |  | // specialization. Most types stabilize by the second execution, too:
 | 
					
						
							|  |  |  | #define ADAPTIVE_WARMUP_VALUE 1
 | 
					
						
							|  |  |  | #define ADAPTIVE_WARMUP_BACKOFF 1
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A value of 52 means that we attempt to re-specialize after 53 misses (a prime
 | 
					
						
							|  |  |  | // number, useful for avoiding artifacts if every nth value is a different type
 | 
					
						
							|  |  |  | // or something). Setting the backoff to 0 means that the counter is reset to
 | 
					
						
							|  |  |  | // the same state as a warming-up instruction (value == 1, backoff == 1) after
 | 
					
						
							|  |  |  | // deoptimization. This isn't strictly necessary, but it is bit easier to reason
 | 
					
						
							|  |  |  | // about when thinking about the opcode transitions as a state machine:
 | 
					
						
							|  |  |  | #define ADAPTIVE_COOLDOWN_VALUE 52
 | 
					
						
							|  |  |  | #define ADAPTIVE_COOLDOWN_BACKOFF 0
 | 
					
						
							| 
									
										
										
										
											2022-05-31 11:58:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define MAX_BACKOFF_VALUE (16 - ADAPTIVE_BACKOFF_BITS)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline uint16_t | 
					
						
							|  |  |  | adaptive_counter_bits(int value, int backoff) { | 
					
						
							|  |  |  |     return (value << ADAPTIVE_BACKOFF_BITS) | | 
					
						
							| 
									
										
										
										
											2022-12-14 11:12:53 +00:00
										 |  |  |         (backoff & ((1<<ADAPTIVE_BACKOFF_BITS)-1)); | 
					
						
							| 
									
										
										
										
											2022-05-31 11:58:26 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline uint16_t | 
					
						
							| 
									
										
										
										
											2022-11-09 10:50:09 -08:00
										 |  |  | adaptive_counter_warmup(void) { | 
					
						
							|  |  |  |     return adaptive_counter_bits(ADAPTIVE_WARMUP_VALUE, | 
					
						
							|  |  |  |                                  ADAPTIVE_WARMUP_BACKOFF); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline uint16_t | 
					
						
							|  |  |  | adaptive_counter_cooldown(void) { | 
					
						
							|  |  |  |     return adaptive_counter_bits(ADAPTIVE_COOLDOWN_VALUE, | 
					
						
							|  |  |  |                                  ADAPTIVE_COOLDOWN_BACKOFF); | 
					
						
							| 
									
										
										
										
											2022-05-31 11:58:26 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline uint16_t | 
					
						
							|  |  |  | adaptive_counter_backoff(uint16_t counter) { | 
					
						
							|  |  |  |     unsigned int backoff = counter & ((1<<ADAPTIVE_BACKOFF_BITS)-1); | 
					
						
							|  |  |  |     backoff++; | 
					
						
							|  |  |  |     if (backoff > MAX_BACKOFF_VALUE) { | 
					
						
							|  |  |  |         backoff = MAX_BACKOFF_VALUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     unsigned int value = (1 << backoff) - 1; | 
					
						
							|  |  |  |     return adaptive_counter_bits(value, backoff); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-09 12:18:45 +00:00
										 |  |  | extern uint32_t _Py_next_func_version; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-20 13:00:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-11 20:40:43 +00:00
										 |  |  | /* Comparison bit masks. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Note this evaluates its arguments twice each */ | 
					
						
							|  |  |  | #define COMPARISON_BIT(x, y) (1 << (2 * ((x) >= (y)) + ((x) <= (y))))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * The following bits are chosen so that the value of | 
					
						
							|  |  |  |  * COMPARSION_BIT(left, right) | 
					
						
							|  |  |  |  * masked by the values below will be non-zero if the | 
					
						
							|  |  |  |  * comparison is true, and zero if it is false */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This is for values that are unordered, ie. NaN, not types that are unordered, e.g. sets */ | 
					
						
							|  |  |  | #define COMPARISON_UNORDERED 1
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define COMPARISON_LESS_THAN 2
 | 
					
						
							|  |  |  | #define COMPARISON_GREATER_THAN 4
 | 
					
						
							|  |  |  | #define COMPARISON_EQUALS 8
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define COMPARISON_NOT_EQUALS (COMPARISON_UNORDERED | COMPARISON_LESS_THAN | COMPARISON_GREATER_THAN)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-12 12:04:55 +01:00
										 |  |  | extern int _Py_Instrument(PyCodeObject *co, PyInterpreterState *interp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern int _Py_GetBaseOpcode(PyCodeObject *code, int offset); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-02 11:46:18 +01:00
										 |  |  | extern int _PyInstruction_GetLength(PyCodeObject *code, int offset); | 
					
						
							| 
									
										
										
										
											2023-01-11 20:40:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-03 21:30:58 +09:00
										 |  |  | #ifdef __cplusplus
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #endif /* !Py_INTERNAL_CODE_H */
 |