Почему у CPython есть код операции "POP_BLOCK"? - PullRequest
0 голосов
/ 09 мая 2018

Какова цель отслеживания блоков в байт-коде Python?

В документации здесь упоминается:

... Для каждого кадра имеется стек блоков, обозначающих вложенные циклы, операторы try и т. Д.

Но на самом деле они не кажутся необходимыми для выполнения циклов. Например, играя с REPL, я вижу:

>>> def foo():
...   while True:
...     print('hi')
... 
>>> for inst in list(dis.get_instructions(foo)): print(inst)
... 
Instruction(opname='SETUP_LOOP', opcode=120, arg=12, argval=14, argrepr='to 14', offset=0, starts_line=2, is_jump_target=False)
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=2, starts_line=3, is_jump_target=True)
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval='hi', argrepr="'hi'", offset=4, starts_line=None, is_jump_target=False)
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=6, starts_line=None, is_jump_target=False)
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=8, starts_line=None, is_jump_target=False)
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=2, argval=2, argrepr='', offset=10, starts_line=None, is_jump_target=False)
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=12, starts_line=None, is_jump_target=False)
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=14, starts_line=None, is_jump_target=True)
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=16, starts_line=None, is_jump_target=False)

Указанная инструкция JUMP_ABSOLUTE переходит к указанной инструкции LOAD_GLOBAL. Из простого ознакомления с инструкциями кажется, что коды операций SETUP_LOOP и POP_BLOCK могут быть неактивными.

Из того, что я понимаю, в Python нет блочных переменных, поэтому не нравится, что это также является причиной.

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Байт-коды SETUP_LOOP и POP_BLOCK в вашем примере функции бесполезны, потому что цикл выполняется вечно, но если у вас есть оператор break внутри цикла, будет использоваться инфраструктура, которую они создали в кадре. Интерпретатор поместил бы байт-код BREAK_LOOP там, где произошел оператор break, и использовал бы информацию о блоке, чтобы найти ближайший цикл, из которого можно выйти.

Обратите внимание, что эта часть байт-кода, по-видимому, изменится в Python 3.8 , поэтому вы, возможно, не захотите вкладывать слишком много усилий в понимание того, как он работает в настоящее время. Вы можете прочитать выпуск 17611 на трекере ошибок Python, чтобы увидеть, как обсуждалась эта тема до ее реализации.

0 голосов
/ 09 мая 2018

CPython использует модель стекового компьютера, где временные значения помещаются в стек значений и извлекаются командами, которые их используют.Когда цикл заканчивается, в зависимости от того, как он заканчивается, у него могут остаться значения в стеке значений, которые больше не нужны.

Стек блоков фрейма отслеживает уровень стека значений в начале цикла инесколько других конструкций, поэтому стек значений можно восстановить до состояния, в котором код после цикла / другой конструкции нуждается в стеке. POP_BLOCK - это одна из конструкций, которая восстанавливает стек до состояния входа в блок.

Информация в стеке блоков очень важна для конструкций обработки исключений, поскольку при возникновении исключения стек значений может находиться во всевозможных странных состояниях.Это не так необходимо для циклов, и я полагаю, что патч , входящий в CPython 3.8, устранит записи стеков блоков для циклов, вместо этого компилятор определит необходимую обработку статически.

...