This document describes CPython's bytecode instruction format, the opcode definition system, and the structure of code objects. It covers how instructions are encoded, how the single source of truth definition files generate the runtime evaluation loops, and the metadata associated with Python's executable units.
For details on how source code is transformed into these instructions, see [2.2 AST, Compiler, and Bytecode Assembly]. For the execution of these instructions, see [3.1 Bytecode Interpreter and Evaluation Loop].
CPython bytecode is a sequence of 16-bit units called _Py_CODEUNIT. Each unit consists of an 8-bit opcode followed by an 8-bit operand (oparg). This 2-byte structure forms the atomic executable instruction unit for the Python virtual machine.
Opcode: The operation identifier, an 8-bit code. The full set of opcode numbers and their meanings are enumerated in Include/opcode_ids.h.
Oparg: An 8-bit operand whose interpretation depends on the opcode. For instructions needing larger arguments, one or more EXTENDED_ARG opcodes precede it, shifting and extending the argument bits to form larger numbers.
Inline Caches: Many opcodes are followed by zero or more cache entries (typically 2 bytes each), which store data used for adaptive specialization and quickening, such as type checks, counters, or other state.
Instructions are byte-aligned on 2-byte (_Py_CODEUNIT) boundaries for efficient decoding.
Jump and exception handler offsets work in terms of instruction counts (indexed by _Py_CODEUNIT), not bytes.
The inline cache schemes and adaptive specialization rely on metadata tables generated from the central bytecode definitions, allowing instruction execution to be optimized dynamically.
Sources: Python/bytecodes.c48-90 Include/opcode_ids.h Include/internal/pycore_opcode_metadata.h15-94 Python/generated_cases.c.h20-60
PyCodeObject)The immutable PyCodeObject holds the compiled representation of Python code including bytecode, constants, names, and auxiliary metadata.
co_code_adaptive
This is the mutable bytecode array for adaptive specialization, stored as _Py_CODEUNIT sequence and modified in place by optimizations and quickening.
Python/bytecodes.c175-180
co_consts
A tuple containing literals, nested code objects, and other constant values used by the bytecode.
Python/optimizer_bytecodes.c79-83
_co_instrumentation_version
Tracks instrumentation/version state for runtime monitoring and re-instrumenting code objects when tracing or debugging states change.
Python/bytecodes.c190-195 Python/executor_cases.c.h112-118
co_executors
Points to an array of Tier 2 executors—specialized micro-op blackboxes stored directly alongside code for optimized JIT execution.
Python/optimizer.c40-115
The frame for evaluation (_PyInterpreterFrame) holds a reference to the code object, the instruction pointer, and local variables (localsplus).
Python/bytecodes.c175-205
Sources: Python/bytecodes.c175-200 Python/optimizer.c40-115 Python/executor_cases.c.h110-130 Python/optimizer_bytecodes.c79-90
CPython uses a domain-specific language embedded in Python/bytecodes.c as the authoritative instruction definition source. This file is used by a suite of Python scripts for code and metadata generation.
Python/bytecodes.c defines opcodes and micro-ops using macros such as inst(name, ...), op(name, ...), and family(name, ...) for specialization sets. It includes dummy variable declarations and rich annotations used for automatic code generation.
Python/bytecodes.c1-180
Tools/cases_generator contains Python generators like tier1_generator.py and tier2_generator.py which parse these DSLs to produce .h header files used in compilation.
Key generated headers include:
Python/generated_cases.c.h: Implements the Tier 1 interpreter's opcode switch-cases.Python/executor_cases.c.h: Implements Tier 2 micro-op interpreter cases.Include/internal/pycore_opcode_metadata.h: Contains static metadata, such as stack effects, cache sizes, and inlining info for opcodes and micro-ops.This infrastructure ensures consistency between high-level opcode definitions and the generated optimized runtime code, enabling specialization and quickening.
The bytecodes DSL supports instruction families. For example, BINARY_OP dynamically specializes into BINARY_OP_ADD_FLOAT or BINARY_OP_ADD_INT based on operand types encountered at runtime (quickening).
Usage counters and guards are built into the instruction dispatch logic to trigger specialization.
Specialization guards, such as _GUARD_TOS_FLOAT, check that the operand types remain stable, facilitating the use of optimized micro-ops.
Sources: Python/bytecodes.c1-180 Tools/cases_generator/tier1_generator.py lines summarized Python/generated_cases.c.h1-172 Include/internal/pycore_opcode_metadata.h1-38
Tier 2 execution uses micro-operations (UOps), which are finer-grained than Tier 1 bytecodes. The Tier 2 optimizer lowers complex bytecodes into UOp traces for more precise optimization and code generation.
Include/internal/pycore_uop_ids.h assigns unique enumerations for every UOp including internal operations like _SET_IP (set instruction pointer) or _EXIT_TRACE.
Include/internal/pycore_uop_ids.h10-40
Include/internal/pycore_uop_metadata.h defines properties for each micro-op, such as flags indicating errors, purity, exit behavior, and stack inputs/outputs. This facilitates detailed static and dynamic reasoning about micro-op traces.
Include/internal/pycore_uop_metadata.h20-120
Python/optimizer_analysis.c implements abstract interpretation on micro-op traces (_Py_UOpsAbstractFrame), enabling the optimizer to deduce constant values, eliminate redundant guards, and fold operations. This symbolic analysis uses a lattice of symbol states to optimize execution without losing correctness.
Python/optimizer_analysis.c58-83 Python/optimizer_analysis.c181-210
The Tier 2 optimizer produces _PyExecutorObject instances encapsulating specialized instruction sequences and caches them in code objects for reuse during execution.
Python/optimizer.c40-115
Sources: Include/internal/pycore_uop_ids.h10-40 Include/internal/pycore_uop_metadata.h20-120 Python/optimizer_analysis.c50-80 Python/executor_cases.c.h10-130 Python/optimizer_bytecodes.c10-70
| Metadata Structure | Purpose | Source File |
|---|---|---|
_PyOpcode_num_popped | Returns the number of stack elements popped by an opcode based on opcode and oparg | Include/internal/pycore_opcode_metadata.h36-250 |
_PyUop_Flags | Bitmask flags describing micro-op traits like HAS_EXIT_FLAG, HAS_ERROR_FLAG, etc. | Include/internal/pycore_uop_metadata.h37-117 |
_PyUop_Caching | Metadata for Tier 2 register caching of stack entries (_tos_cache0, etc.) | Include/internal/pycore_uop_metadata.h28-32 Python/executor_cases.c.h20-60 |
IS_PSEUDO_INSTR | Macro to identify pseudo instructions used only in compilation (like SETUP_FINALLY) | Include/internal/pycore_opcode_metadata.h20-32 |
_PyOpcode_uop_name | String representations of micro-op names for debugging and disassembly output | Include/internal/pycore_uop_metadata.h18 |
These metadata constructs provide both runtime and compile-time information essential for bytecode dispatch, optimization, and tiered execution in CPython.
Sources: Include/internal/pycore_opcode_metadata.h20-250 Include/internal/pycore_uop_metadata.h20-120 Python/executor_cases.c.h20-60
Sources: Synthesized from Python/bytecodes.c Python/generated_cases.c.h Python/optimizer.c Python/ceval.c1-200
Python/bytecodes.c Python/bytecodes.c1-180Python/generated_cases.c.h Python/generated_cases.c.h1-172Python/executor_cases.c.h Python/executor_cases.c.h1-130Include/internal/pycore_opcode_metadata.h Include/internal/pycore_opcode_metadata.h20-250Include/internal/pycore_uop_metadata.h Include/internal/pycore_uop_metadata.h20-120Python/optimizer.c, Python/optimizer_analysis.c Python/optimizer.c1-115 Python/optimizer_analysis.c50-210Python/ceval.c Python/ceval.c1-200This completes the detailed wiki page on Python's Bytecode Format and Opcode Definitions with explicit code references and diagrams bridging natural language concepts with code entities.
Refresh this wiki