Skip to main content

Objects/codeobject.c (part 6)

Source:

cpython 3.14 @ ab2d84fe1023/Objects/codeobject.c

This annotation covers code object construction and the 3.11+ format. See objects_codeobject5_detail for co_consts, co_names, co_linetable, and co_lnotab.

Map

LinesSymbolRole
1-80code.__new__Construct a code object from parameters
81-180code.replaceClone a code object with changed fields
181-280localsplusnames / localspluskindsUnified locals + cells + freevars table
281-380Exception tableMapping from instruction range to handler
381-600_PyCode_GetCodeReconstruct the instruction bytes

Reading

localsplusnames / localspluskinds

// CPython: Objects/codeobject.c:240 _PyCode_Validate_Varnames
/* localspluskinds: bit flags per name
CO_FAST_LOCAL: 0x20 — regular local
CO_FAST_CELL: 0x40 — cell variable (closed over by inner function)
CO_FAST_FREE: 0x80 — free variable (from outer scope cell)
CO_FAST_ARG: 0x04 — positional argument
CO_FAST_KWARG: 0x08 — keyword argument
*/

CPython 3.11+ unified co_varnames, co_cellvars, and co_freevars into a single co_localsplusnames tuple. co_localspluskinds is a bytes object (one byte per name) encoding which category each name falls into. LOAD_FAST and LOAD_DEREF share the same index space.

Exception table

// CPython: Objects/codeobject.c:620 exception table encoding
/* Entry: (start, size, target, depth_lasti)
start: instruction offset of try block start
size: number of instructions in try block
target: instruction offset of except handler
depth: stack depth at start
lasti: whether to push the last-instruction value */
static int
parse_exception_table(PyCodeObject *code, ...)
{
/* Variable-length encoding: each entry uses 3-6 bytes */
/* start_offset and size are encoded as uvarint (1-2 bytes each) */
...
}

The exception table replaces the old block stack. Each try/except has an entry: (start, end, handler, stack_depth). When an exception occurs, the interpreter scans the table to find the handler for the current instruction offset.

code.replace

// CPython: Objects/codeobject.c:840 code_replace_impl
static PyObject *
code_replace_impl(PyCodeObject *self, ...)
{
/* Create a new code object, replacing specified fields */
/* Used by: functools.wraps, unittest.mock, coverage.py */
return _PyCode_New(...);
}

code.replace(co_consts=new_consts) creates a clone with modified constants. Used by testing tools to inject mocks, and by coverage tools to instrument bytecode. The new code object shares most fields with the original.

gopy notes

code.__new__ is objects.NewCodeObject in objects/code.go. localsplusnames is a Go []string. localspluskinds is a []byte. The exception table is []objects.ExceptionTableEntry with binary search for fast lookup. code.replace clones the objects.Code struct with the override fields applied.