mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	bpo-40421: Add Include/cpython/code.h header file (GH-19756)
bpo-35134, bpo-40421: Add Include/cpython/code.h header file. code.h now defines PyCodeObject type in the limited C API. It is now included by Python.h. Give a name to the PyCodeObject structure: it is now called "struct PyCodeObject". So it becomes possible to define PyCodeObject as "struct PyCodeObject" in the limited C API without defining the structure.
This commit is contained in:
		
							parent
							
								
									7c59d7c986
								
							
						
					
					
						commit
						b8f704d219
					
				
					 7 changed files with 175 additions and 165 deletions
				
			
		|  | @ -114,6 +114,7 @@ | |||
| #include "classobject.h" | ||||
| #include "fileobject.h" | ||||
| #include "pycapsule.h" | ||||
| #include "code.h" | ||||
| #include "pyframe.h" | ||||
| #include "traceback.h" | ||||
| #include "sliceobject.h" | ||||
|  |  | |||
							
								
								
									
										168
									
								
								Include/code.h
									
										
									
									
									
								
							
							
						
						
									
										168
									
								
								Include/code.h
									
										
									
									
									
								
							|  | @ -1,180 +1,20 @@ | |||
| /* Definitions for bytecode */ | ||||
| 
 | ||||
| #ifndef Py_LIMITED_API | ||||
| #ifndef Py_CODE_H | ||||
| #define Py_CODE_H | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| typedef uint16_t _Py_CODEUNIT; | ||||
| 
 | ||||
| #ifdef WORDS_BIGENDIAN | ||||
| #  define _Py_OPCODE(word) ((word) >> 8) | ||||
| #  define _Py_OPARG(word) ((word) & 255) | ||||
| #else | ||||
| #  define _Py_OPCODE(word) ((word) & 255) | ||||
| #  define _Py_OPARG(word) ((word) >> 8) | ||||
| #endif | ||||
| 
 | ||||
| typedef struct _PyOpcache _PyOpcache; | ||||
| 
 | ||||
| /* Bytecode object */ | ||||
| typedef struct { | ||||
|     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_lnotab;        /* 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.
 | ||||
| } PyCodeObject; | ||||
| 
 | ||||
| /* Masks for co_flags above */ | ||||
| #define CO_OPTIMIZED    0x0001 | ||||
| #define CO_NEWLOCALS    0x0002 | ||||
| #define CO_VARARGS      0x0004 | ||||
| #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) */ | ||||
| #define CO_COROUTINE            0x0080 | ||||
| #define CO_ITERABLE_COROUTINE   0x0100 | ||||
| #define CO_ASYNC_GENERATOR      0x0200 | ||||
| 
 | ||||
| /* bpo-39562: These constant values are changed in Python 3.9
 | ||||
|    to prevent collision with compiler flags. CO_FUTURE_ and PyCF_ | ||||
|    constants must be kept unique. PyCF_ constants can use bits from | ||||
|    0x0100 to 0x10000. CO_FUTURE_ constants use bits starting at 0x20000. */ | ||||
| #define CO_FUTURE_DIVISION      0x20000 | ||||
| #define CO_FUTURE_ABSOLUTE_IMPORT 0x40000 /* do absolute imports by default */ | ||||
| #define CO_FUTURE_WITH_STATEMENT  0x80000 | ||||
| #define CO_FUTURE_PRINT_FUNCTION  0x100000 | ||||
| #define CO_FUTURE_UNICODE_LITERALS 0x200000 | ||||
| 
 | ||||
| #define CO_FUTURE_BARRY_AS_BDFL  0x400000 | ||||
| #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. | ||||
| */ | ||||
| #define PY_PARSER_REQUIRES_FUTURE_KEYWORD | ||||
| 
 | ||||
| #define CO_MAXBLOCKS 20 /* Max static block nesting within a function */ | ||||
| 
 | ||||
| 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)) | ||||
| 
 | ||||
| /* Public interface */ | ||||
| PyAPI_FUNC(PyCodeObject *) PyCode_New( | ||||
|         int, int, int, int, int, PyObject *, PyObject *, | ||||
|         PyObject *, PyObject *, PyObject *, PyObject *, | ||||
|         PyObject *, PyObject *, int, PyObject *); | ||||
| 
 | ||||
| PyAPI_FUNC(PyCodeObject *) PyCode_NewWithPosOnlyArgs( | ||||
|         int, int, int, int, int, int, PyObject *, PyObject *, | ||||
|         PyObject *, PyObject *, PyObject *, PyObject *, | ||||
|         PyObject *, PyObject *, int, PyObject *); | ||||
|         /* same as struct above */ | ||||
| 
 | ||||
| /* Creates a new empty code object with the specified source location. */ | ||||
| PyAPI_FUNC(PyCodeObject *) | ||||
| PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno); | ||||
| 
 | ||||
| /* Return the line number associated with the specified bytecode index
 | ||||
|    in this code object.  If you just need the line number of a frame, | ||||
|    use PyFrame_GetLineNumber() instead. */ | ||||
| PyAPI_FUNC(int) PyCode_Addr2Line(PyCodeObject *, int); | ||||
| 
 | ||||
| /* for internal use only */ | ||||
| typedef struct _addr_pair { | ||||
|         int ap_lower; | ||||
|         int ap_upper; | ||||
| } PyAddrPair; | ||||
| typedef struct PyCodeObject PyCodeObject; | ||||
| 
 | ||||
| #ifndef Py_LIMITED_API | ||||
| /* Update *bounds to describe the first and one-past-the-last instructions in the
 | ||||
|    same line as lasti.  Return the number of that line. | ||||
| */ | ||||
| PyAPI_FUNC(int) _PyCode_CheckLineNumber(PyCodeObject* co, | ||||
|                                         int lasti, PyAddrPair *bounds); | ||||
| 
 | ||||
| /* Create a comparable key used to compare constants taking in account the
 | ||||
|  * object type. It is used to make sure types are not coerced (e.g., float and | ||||
|  * complex) _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms | ||||
|  * | ||||
|  * Return (type(obj), obj, ...): a tuple with variable size (at least 2 items) | ||||
|  * depending on the type and the value. The type is the first item to not | ||||
|  * compare bytes and str which can raise a BytesWarning exception. */ | ||||
| PyAPI_FUNC(PyObject*) _PyCode_ConstantKey(PyObject *obj); | ||||
| #endif | ||||
| 
 | ||||
| PyAPI_FUNC(PyObject*) PyCode_Optimize(PyObject *code, PyObject* consts, | ||||
|                                       PyObject *names, PyObject *lnotab); | ||||
| 
 | ||||
| 
 | ||||
| #ifndef Py_LIMITED_API | ||||
| PyAPI_FUNC(int) _PyCode_GetExtra(PyObject *code, Py_ssize_t index, | ||||
|                                  void **extra); | ||||
| PyAPI_FUNC(int) _PyCode_SetExtra(PyObject *code, Py_ssize_t index, | ||||
|                                  void *extra); | ||||
| #  define Py_CPYTHON_CODE_H | ||||
| #  include  "cpython/code.h" | ||||
| #  undef Py_CPYTHON_CODE_H | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif /* !Py_CODE_H */ | ||||
| #endif /* Py_LIMITED_API */ | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
| #define Py_COMPILE_H | ||||
| 
 | ||||
| #ifndef Py_LIMITED_API | ||||
| #include "code.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
|  |  | |||
							
								
								
									
										165
									
								
								Include/cpython/code.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								Include/cpython/code.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,165 @@ | |||
| #ifndef Py_CPYTHON_CODE_H | ||||
| #  error "this header file must not be included directly" | ||||
| #endif | ||||
| 
 | ||||
| typedef uint16_t _Py_CODEUNIT; | ||||
| 
 | ||||
| #ifdef WORDS_BIGENDIAN | ||||
| #  define _Py_OPCODE(word) ((word) >> 8) | ||||
| #  define _Py_OPARG(word) ((word) & 255) | ||||
| #else | ||||
| #  define _Py_OPCODE(word) ((word) & 255) | ||||
| #  define _Py_OPARG(word) ((word) >> 8) | ||||
| #endif | ||||
| 
 | ||||
| typedef struct _PyOpcache _PyOpcache; | ||||
| 
 | ||||
| /* 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_lnotab;        /* 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.
 | ||||
| }; | ||||
| 
 | ||||
| /* Masks for co_flags above */ | ||||
| #define CO_OPTIMIZED    0x0001 | ||||
| #define CO_NEWLOCALS    0x0002 | ||||
| #define CO_VARARGS      0x0004 | ||||
| #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) */ | ||||
| #define CO_COROUTINE            0x0080 | ||||
| #define CO_ITERABLE_COROUTINE   0x0100 | ||||
| #define CO_ASYNC_GENERATOR      0x0200 | ||||
| 
 | ||||
| /* bpo-39562: These constant values are changed in Python 3.9
 | ||||
|    to prevent collision with compiler flags. CO_FUTURE_ and PyCF_ | ||||
|    constants must be kept unique. PyCF_ constants can use bits from | ||||
|    0x0100 to 0x10000. CO_FUTURE_ constants use bits starting at 0x20000. */ | ||||
| #define CO_FUTURE_DIVISION      0x20000 | ||||
| #define CO_FUTURE_ABSOLUTE_IMPORT 0x40000 /* do absolute imports by default */ | ||||
| #define CO_FUTURE_WITH_STATEMENT  0x80000 | ||||
| #define CO_FUTURE_PRINT_FUNCTION  0x100000 | ||||
| #define CO_FUTURE_UNICODE_LITERALS 0x200000 | ||||
| 
 | ||||
| #define CO_FUTURE_BARRY_AS_BDFL  0x400000 | ||||
| #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. | ||||
| */ | ||||
| #define PY_PARSER_REQUIRES_FUTURE_KEYWORD | ||||
| 
 | ||||
| #define CO_MAXBLOCKS 20 /* Max static block nesting within a function */ | ||||
| 
 | ||||
| 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)) | ||||
| 
 | ||||
| /* Public interface */ | ||||
| PyAPI_FUNC(PyCodeObject *) PyCode_New( | ||||
|         int, int, int, int, int, PyObject *, PyObject *, | ||||
|         PyObject *, PyObject *, PyObject *, PyObject *, | ||||
|         PyObject *, PyObject *, int, PyObject *); | ||||
| 
 | ||||
| PyAPI_FUNC(PyCodeObject *) PyCode_NewWithPosOnlyArgs( | ||||
|         int, int, int, int, int, int, PyObject *, PyObject *, | ||||
|         PyObject *, PyObject *, PyObject *, PyObject *, | ||||
|         PyObject *, PyObject *, int, PyObject *); | ||||
|         /* same as struct above */ | ||||
| 
 | ||||
| /* Creates a new empty code object with the specified source location. */ | ||||
| PyAPI_FUNC(PyCodeObject *) | ||||
| PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno); | ||||
| 
 | ||||
| /* Return the line number associated with the specified bytecode index
 | ||||
|    in this code object.  If you just need the line number of a frame, | ||||
|    use PyFrame_GetLineNumber() instead. */ | ||||
| PyAPI_FUNC(int) PyCode_Addr2Line(PyCodeObject *, int); | ||||
| 
 | ||||
| /* for internal use only */ | ||||
| typedef struct _addr_pair { | ||||
|         int ap_lower; | ||||
|         int ap_upper; | ||||
| } PyAddrPair; | ||||
| 
 | ||||
| /* Update *bounds to describe the first and one-past-the-last instructions in the
 | ||||
|    same line as lasti.  Return the number of that line. | ||||
| */ | ||||
| PyAPI_FUNC(int) _PyCode_CheckLineNumber(PyCodeObject* co, | ||||
|                                         int lasti, PyAddrPair *bounds); | ||||
| 
 | ||||
| /* Create a comparable key used to compare constants taking in account the
 | ||||
|  * object type. It is used to make sure types are not coerced (e.g., float and | ||||
|  * complex) _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms | ||||
|  * | ||||
|  * Return (type(obj), obj, ...): a tuple with variable size (at least 2 items) | ||||
|  * depending on the type and the value. The type is the first item to not | ||||
|  * compare bytes and str which can raise a BytesWarning exception. */ | ||||
| PyAPI_FUNC(PyObject*) _PyCode_ConstantKey(PyObject *obj); | ||||
| 
 | ||||
| PyAPI_FUNC(PyObject*) PyCode_Optimize(PyObject *code, PyObject* consts, | ||||
|                                       PyObject *names, PyObject *lnotab); | ||||
| 
 | ||||
| 
 | ||||
| PyAPI_FUNC(int) _PyCode_GetExtra(PyObject *code, Py_ssize_t index, | ||||
|                                  void **extra); | ||||
| PyAPI_FUNC(int) _PyCode_SetExtra(PyObject *code, Py_ssize_t index, | ||||
|                                  void *extra); | ||||
|  | @ -1086,6 +1086,7 @@ PYTHON_HEADERS= \ | |||
| 		$(srcdir)/Include/cpython/bytearrayobject.h \ | ||||
| 		$(srcdir)/Include/cpython/bytesobject.h \ | ||||
| 		$(srcdir)/Include/cpython/ceval.h \ | ||||
| 		$(srcdir)/Include/cpython/code.h \ | ||||
| 		$(srcdir)/Include/cpython/dictobject.h \ | ||||
| 		$(srcdir)/Include/cpython/fileobject.h \ | ||||
| 		$(srcdir)/Include/cpython/fileutils.h \ | ||||
|  |  | |||
|  | @ -131,6 +131,7 @@ | |||
|     <ClInclude Include="..\Include\cpython\bytearrayobject.h" /> | ||||
|     <ClInclude Include="..\Include\cpython\bytesobject.h" /> | ||||
|     <ClInclude Include="..\Include\cpython\ceval.h" /> | ||||
|     <ClInclude Include="..\Include\cpython\code.h" /> | ||||
|     <ClInclude Include="..\Include\cpython\dictobject.h" /> | ||||
|     <ClInclude Include="..\Include\cpython\fileobject.h" /> | ||||
|     <ClInclude Include="..\Include\cpython\fileutils.h" /> | ||||
|  |  | |||
|  | @ -90,6 +90,9 @@ | |||
|     <ClInclude Include="..\Include\cpython\ceval.h"> | ||||
|       <Filter>Include</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\Include\cpython\code.h"> | ||||
|       <Filter>Include</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\Include\cpython\dictobject.h"> | ||||
|       <Filter>Include</Filter> | ||||
|     </ClInclude> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Victor Stinner
						Victor Stinner