erg/doc/EN/python/bytecode_instructions.md
2022-08-23 20:25:45 +09:00

3.2 KiB

Python Bytecode Instructions

Python bytecode variable manipulation instructions are accessed through namei (name index). This is to realize Python's dynamic variable access (access by string using eval, etc.). Each instruction is 2 bytes, and instructions and arguments are stored in a little endian. Instructions that do not take arguments also use 2 bytes (the argument part is 0).

STORE_NAME(namei)

globals[namei] = stack.pop()

LOAD_NAME(namei)

stack.push(globals[namei])

Only called at the top level.

LOAD_GLOBAL(namei)

stack.push(globals[namei])

To Load what was STORE_NAME at the top level in the inner scope, but namei at the top level is not necessarily the same as namei in a code object of a certain scope (namei, not name, is the same).

LOAD_CONST(namei)

stack.push(consts[namei])

Load constants in the constants table. Currently (Python 3.9), CPython MAKE_FUNCTION every time a lambda function is called "<lambda>".

>>> dis.dis("[1,2,3].map(lambda x: x+1)")
1 0 LOAD_CONST 0 (1)
        2 LOAD_CONST 1 (2)
        4 LOAD_CONST 2 (3)
        6 BUILD_LIST 3
        8 LOAD_ATTR 0 (map)
        10 LOAD_CONST 3 (<code object <lambda> at 0x7f272897fc90, file "<dis>", line 1>)
        12 LOAD_CONST 4 ('<lambda>')
        14 MAKE_FUNCTION 0
        16 CALL_FUNCTION 1
        18 RETURN_VALUE

STORE_FAST(namei)

fastlocals[namei] = stack.pop()

Probably corresponds to STORE_NAME at the top level. This is supposed to store an unreferenced (or single) variable. Is it for optimization that the global space has its own instruction?

LOAD_FAST(namei)

stack.push(fastlocals[namei]) fastlocals is varnames?

LOAD_CLOSURE(namei)

cell = freevars[namei]
stack.push(cell)

After that BUILD_TUPLE is called. It is only called in a closure, and cellvars is supposed to store references in the closure. Unlike LOAD_DEREF, the entire cell (container with references) is pushed onto the stack

STORE_DEREF(namei)

cell = freevars[namei]
cell.set(stack.pop())

Variables without references in the inner scope are STORE_FAST, but referenced variables are STORE_DEREF. In Python, the reference count is increased or decreased within this instruction

LOAD_DEREF(namei)

cell = freevars[namei]
stack.push(cell.get())

Name List

varnames

List of names of internal variables of the function corresponding to fast_locals. Even if there is a variable with the same name in names, it is not basically the same (it is newly created, and the outside variable cannot be accessed from its scope). In other words, variables defined in scope without external references go into varnames

names

Corresponding to globals. A list of names of external constants (reference only) used in a scope (even ordinary variables at the top level go into names). In other words, constants defined outside the scope go into names

free variable

Corresponds to freevars. Variables captured by closure. It behaves static within the same function instance.

cell variables

Corresponds to cellvars. Variables captured by an inner closure function within a function. A copy is made, so the original variable remains intact.