Skip to main content

Python/ceval_macros.h

cpython 3.14 @ ab2d84fe1023/Python/ceval_macros.h

ceval_macros.h is included once, at the top of Python/ceval.c, and is never compiled as a standalone translation unit. Every macro defined here is scoped to the eval-loop function _PyEval_EvalFrameDefault. Because CPython's main eval loop is a giant C function, using macros instead of inline helpers keeps the compiler's optimizer from generating unnecessary function prologues on hot paths.

The file divides naturally into four groups: stack manipulation (STACK_PUSH, STACK_POP, PEEK, POKE), control-flow helpers (JUMPBY, DISPATCH, DISPATCH_GOTO), error-handling shortcuts (ERROR_IF, DEOPT_IF), and local variable accessors (GETLOCAL, SETLOCAL). Together they form the vocabulary that every instruction body in ceval.c and the Tier-1 specialising adaptive interpreter uses.

The macros are deliberately low-level. STACK_PUSH is a raw pointer increment, JUMPBY is a signed offset applied to the program counter, and ERROR_IF expands to a conditional goto error that lands at the unified error handler at the bottom of the eval loop. This design means that instruction bodies read like pseudocode while the real mechanics stay in one reviewed header.

Map

LinesSymbolRolegopy
1-30stack sentinel macrosSTACK_LEVEL, EMPTY, TOPnot ported
31-60STACK_PUSH / STACK_POPpush/pop PyObject * on the value stacknot ported
61-80PEEK / POKEread/write stack slot at depth N without adjusting SPnot ported
81-110JUMPBY / JUMPTOadvance or set the program counternot ported
111-140DISPATCH / DISPATCH_GOTOre-enter the opcode dispatch switchnot ported
141-165ERROR_IF / DEOPT_IFconditional jump to error or deopt labelnot ported
166-200GETLOCAL / SETLOCALaccess fast-locals array with reference countingnot ported

Reading

Stack sentinel macros (lines 1 to 30)

cpython 3.14 @ ab2d84fe1023/Python/ceval_macros.h#L1-30

The opening block defines STACK_LEVEL as ((int)(stack_pointer - _PyFrame_Stackbase(frame))), which gives the current depth as a signed integer. EMPTY() checks that depth is zero. TOP is sugar for PEEK(1), reading the object sitting at the top of stack without popping it. These three macros appear in assertion guards scattered through the instruction bodies.

#define STACK_LEVEL() ((int)(stack_pointer - _PyFrame_Stackbase(frame)))
#define EMPTY() (STACK_LEVEL() == 0)
#define TOP (PEEK(1))

Push, pop, and indexed peek (lines 31 to 80)

cpython 3.14 @ ab2d84fe1023/Python/ceval_macros.h#L31-80

STACK_PUSH(v) increments stack_pointer then writes v into the new slot. STACK_POP() decrements first and returns the evicted value. PEEK(n) reads stack_pointer[-n] without moving the pointer, and POKE(n, v) writes into that same slot. These four macros implement every stack operation in instruction bodies without any function-call overhead.

#define STACK_PUSH(val) (*stack_pointer++ = (val))
#define STACK_POP() (*--stack_pointer)
#define PEEK(n) (stack_pointer[-(n)])
#define POKE(n, val) (stack_pointer[-(n)] = (val))

Program-counter helpers (lines 81 to 140)

cpython 3.14 @ ab2d84fe1023/Python/ceval_macros.h#L81-140

JUMPBY(x) applies a signed word offset to next_instr, implementing relative jumps for FOR_ITER, JUMP_FORWARD, and the branch instructions. JUMPTO(x) sets next_instr to an absolute instruction index, used by the dispatcher after computing a jump target. DISPATCH and DISPATCH_GOTO re-enter the top of the switch: DISPATCH is used at the end of non-branching instructions, while DISPATCH_GOTO is used inside specialised instruction bodies that fall through from a different case.

#define JUMPBY(x) (next_instr += (x))
#define JUMPTO(x) (next_instr = first_instr + (x))
#define DISPATCH() goto fast_next_opcode
#define DISPATCH_GOTO() goto dispatch_opcode

Error and deopt exits (lines 141 to 200)

cpython 3.14 @ ab2d84fe1023/Python/ceval_macros.h#L141-200

ERROR_IF(cond, label) expands to if (cond) goto label, where label is almost always error. This keeps instruction bodies readable: one line per possible failure, each reading like a postcondition. DEOPT_IF(cond, name) jumps to the deoptimisation trampoline for name, backing out a specialised instruction to its generic form. GETLOCAL(i) and SETLOCAL(i, val) wrap frame->localsplus[i] with the necessary Py_XDECREF on the outgoing value.

#define ERROR_IF(cond, label) do { if (cond) goto label; } while (0)
#define DEOPT_IF(cond, name) do { if (cond) goto DEOPT_##name; } while (0)
#define GETLOCAL(i) (frame->localsplus[i])
#define SETLOCAL(i, val) do { \
PyObject *_tmp = GETLOCAL(i); \
GETLOCAL(i) = (val); \
Py_XDECREF(_tmp); \
} while (0)

gopy mirror

Not yet ported.