Issue #26647: Python interpreter now uses 16-bit wordcode instead of bytecode.
Patch by Demur Rumed.
This commit is contained in:
parent
c35f491a06
commit
b0f80b0312
|
@ -31,9 +31,9 @@ the following command can be used to display the disassembly of
|
|||
|
||||
>>> dis.dis(myfunc)
|
||||
2 0 LOAD_GLOBAL 0 (len)
|
||||
3 LOAD_FAST 0 (alist)
|
||||
6 CALL_FUNCTION 1
|
||||
9 RETURN_VALUE
|
||||
2 LOAD_FAST 0 (alist)
|
||||
4 CALL_FUNCTION 1
|
||||
6 RETURN_VALUE
|
||||
|
||||
(The "2" is a line number).
|
||||
|
||||
|
@ -682,8 +682,7 @@ iterations of the loop.
|
|||
.. XXX explain the WHY stuff!
|
||||
|
||||
|
||||
All of the following opcodes expect arguments. An argument is two bytes, with
|
||||
the more significant byte last.
|
||||
All of the following opcodes use their arguments.
|
||||
|
||||
.. opcode:: STORE_NAME (namei)
|
||||
|
||||
|
|
|
@ -79,9 +79,9 @@ class PythonValuesTestCase(unittest.TestCase):
|
|||
continue
|
||||
items.append((entry.name.decode("ascii"), entry.size))
|
||||
|
||||
expected = [("__hello__", 161),
|
||||
("__phello__", -161),
|
||||
("__phello__.spam", 161),
|
||||
expected = [("__hello__", 139),
|
||||
("__phello__", -139),
|
||||
("__phello__.spam", 139),
|
||||
]
|
||||
self.assertEqual(items, expected, "PyImport_FrozenModules example "
|
||||
"in Doc/library/ctypes.rst may be out of date")
|
||||
|
|
35
Lib/dis.py
35
Lib/dis.py
|
@ -285,7 +285,6 @@ def _get_instructions_bytes(code, varnames=None, names=None, constants=None,
|
|||
"""
|
||||
labels = findlabels(code)
|
||||
starts_line = None
|
||||
free = None
|
||||
for offset, op, arg in _unpack_opargs(code):
|
||||
if linestarts is not None:
|
||||
starts_line = linestarts.get(offset, None)
|
||||
|
@ -296,7 +295,7 @@ def _get_instructions_bytes(code, varnames=None, names=None, constants=None,
|
|||
argrepr = ''
|
||||
if arg is not None:
|
||||
# Set argval to the dereferenced value of the argument when
|
||||
# availabe, and argrepr to the string representation of argval.
|
||||
# available, and argrepr to the string representation of argval.
|
||||
# _disassemble_bytes needs the string repr of the
|
||||
# raw name index for LOAD_GLOBAL, LOAD_CONST, etc.
|
||||
argval = arg
|
||||
|
@ -305,7 +304,7 @@ def _get_instructions_bytes(code, varnames=None, names=None, constants=None,
|
|||
elif op in hasname:
|
||||
argval, argrepr = _get_name_info(arg, names)
|
||||
elif op in hasjrel:
|
||||
argval = offset + 3 + arg
|
||||
argval = offset + 2 + arg
|
||||
argrepr = "to " + repr(argval)
|
||||
elif op in haslocal:
|
||||
argval, argrepr = _get_name_info(arg, varnames)
|
||||
|
@ -352,23 +351,15 @@ def _disassemble_str(source, *, file=None):
|
|||
disco = disassemble # XXX For backwards compatibility
|
||||
|
||||
def _unpack_opargs(code):
|
||||
# enumerate() is not an option, since we sometimes process
|
||||
# multiple elements on a single pass through the loop
|
||||
extended_arg = 0
|
||||
n = len(code)
|
||||
i = 0
|
||||
while i < n:
|
||||
for i in range(0, len(code), 2):
|
||||
op = code[i]
|
||||
offset = i
|
||||
i = i+1
|
||||
arg = None
|
||||
if op >= HAVE_ARGUMENT:
|
||||
arg = code[i] + code[i+1]*256 + extended_arg
|
||||
extended_arg = 0
|
||||
i = i+2
|
||||
if op == EXTENDED_ARG:
|
||||
extended_arg = arg*65536
|
||||
yield (offset, op, arg)
|
||||
arg = code[i+1] | extended_arg
|
||||
extended_arg = (arg << 8) if op == EXTENDED_ARG else 0
|
||||
else:
|
||||
arg = None
|
||||
yield (i, op, arg)
|
||||
|
||||
def findlabels(code):
|
||||
"""Detect all offsets in a byte code which are jump targets.
|
||||
|
@ -379,14 +370,14 @@ def findlabels(code):
|
|||
labels = []
|
||||
for offset, op, arg in _unpack_opargs(code):
|
||||
if arg is not None:
|
||||
label = -1
|
||||
if op in hasjrel:
|
||||
label = offset + 3 + arg
|
||||
label = offset + 2 + arg
|
||||
elif op in hasjabs:
|
||||
label = arg
|
||||
if label >= 0:
|
||||
if label not in labels:
|
||||
labels.append(label)
|
||||
else:
|
||||
continue
|
||||
if label not in labels:
|
||||
labels.append(label)
|
||||
return labels
|
||||
|
||||
def findlinestarts(code):
|
||||
|
|
|
@ -225,6 +225,7 @@ _code_type = type(_write_atomic.__code__)
|
|||
# Python 3.5b2 3350 (add GET_YIELD_FROM_ITER opcode #24400)
|
||||
# Python 3.6a0 3360 (add FORMAT_VALUE opcode #25483
|
||||
# Python 3.6a0 3361 (lineno delta of code.co_lnotab becomes signed)
|
||||
# Python 3.6a0 3370 (16 bit wordcode)
|
||||
#
|
||||
# MAGIC must change whenever the bytecode emitted by the compiler may no
|
||||
# longer be understood by older implementations of the eval loop (usually
|
||||
|
@ -233,7 +234,7 @@ _code_type = type(_write_atomic.__code__)
|
|||
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
|
||||
# in PC/launcher.c must also be updated.
|
||||
|
||||
MAGIC_NUMBER = (3361).to_bytes(2, 'little') + b'\r\n'
|
||||
MAGIC_NUMBER = (3370).to_bytes(2, 'little') + b'\r\n'
|
||||
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
|
||||
|
||||
_PYCACHE = '__pycache__'
|
||||
|
|
|
@ -40,41 +40,41 @@ class _C:
|
|||
|
||||
dis_c_instance_method = """\
|
||||
%3d 0 LOAD_FAST 1 (x)
|
||||
3 LOAD_CONST 1 (1)
|
||||
6 COMPARE_OP 2 (==)
|
||||
9 LOAD_FAST 0 (self)
|
||||
12 STORE_ATTR 0 (x)
|
||||
15 LOAD_CONST 0 (None)
|
||||
18 RETURN_VALUE
|
||||
2 LOAD_CONST 1 (1)
|
||||
4 COMPARE_OP 2 (==)
|
||||
6 LOAD_FAST 0 (self)
|
||||
8 STORE_ATTR 0 (x)
|
||||
10 LOAD_CONST 0 (None)
|
||||
12 RETURN_VALUE
|
||||
""" % (_C.__init__.__code__.co_firstlineno + 1,)
|
||||
|
||||
dis_c_instance_method_bytes = """\
|
||||
0 LOAD_FAST 1 (1)
|
||||
3 LOAD_CONST 1 (1)
|
||||
6 COMPARE_OP 2 (==)
|
||||
9 LOAD_FAST 0 (0)
|
||||
12 STORE_ATTR 0 (0)
|
||||
15 LOAD_CONST 0 (0)
|
||||
18 RETURN_VALUE
|
||||
2 LOAD_CONST 1 (1)
|
||||
4 COMPARE_OP 2 (==)
|
||||
6 LOAD_FAST 0 (0)
|
||||
8 STORE_ATTR 0 (0)
|
||||
10 LOAD_CONST 0 (0)
|
||||
12 RETURN_VALUE
|
||||
"""
|
||||
|
||||
dis_c_class_method = """\
|
||||
%3d 0 LOAD_FAST 1 (x)
|
||||
3 LOAD_CONST 1 (1)
|
||||
6 COMPARE_OP 2 (==)
|
||||
9 LOAD_FAST 0 (cls)
|
||||
12 STORE_ATTR 0 (x)
|
||||
15 LOAD_CONST 0 (None)
|
||||
18 RETURN_VALUE
|
||||
2 LOAD_CONST 1 (1)
|
||||
4 COMPARE_OP 2 (==)
|
||||
6 LOAD_FAST 0 (cls)
|
||||
8 STORE_ATTR 0 (x)
|
||||
10 LOAD_CONST 0 (None)
|
||||
12 RETURN_VALUE
|
||||
""" % (_C.cm.__code__.co_firstlineno + 2,)
|
||||
|
||||
dis_c_static_method = """\
|
||||
%3d 0 LOAD_FAST 0 (x)
|
||||
3 LOAD_CONST 1 (1)
|
||||
6 COMPARE_OP 2 (==)
|
||||
9 STORE_FAST 0 (x)
|
||||
12 LOAD_CONST 0 (None)
|
||||
15 RETURN_VALUE
|
||||
2 LOAD_CONST 1 (1)
|
||||
4 COMPARE_OP 2 (==)
|
||||
6 STORE_FAST 0 (x)
|
||||
8 LOAD_CONST 0 (None)
|
||||
10 RETURN_VALUE
|
||||
""" % (_C.sm.__code__.co_firstlineno + 2,)
|
||||
|
||||
# Class disassembling info has an extra newline at end.
|
||||
|
@ -95,23 +95,23 @@ def _f(a):
|
|||
|
||||
dis_f = """\
|
||||
%3d 0 LOAD_GLOBAL 0 (print)
|
||||
3 LOAD_FAST 0 (a)
|
||||
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
|
||||
9 POP_TOP
|
||||
2 LOAD_FAST 0 (a)
|
||||
4 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
|
||||
6 POP_TOP
|
||||
|
||||
%3d 10 LOAD_CONST 1 (1)
|
||||
13 RETURN_VALUE
|
||||
%3d 8 LOAD_CONST 1 (1)
|
||||
10 RETURN_VALUE
|
||||
""" % (_f.__code__.co_firstlineno + 1,
|
||||
_f.__code__.co_firstlineno + 2)
|
||||
|
||||
|
||||
dis_f_co_code = """\
|
||||
0 LOAD_GLOBAL 0 (0)
|
||||
3 LOAD_FAST 0 (0)
|
||||
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
|
||||
9 POP_TOP
|
||||
10 LOAD_CONST 1 (1)
|
||||
13 RETURN_VALUE
|
||||
2 LOAD_FAST 0 (0)
|
||||
4 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
|
||||
6 POP_TOP
|
||||
8 LOAD_CONST 1 (1)
|
||||
10 RETURN_VALUE
|
||||
"""
|
||||
|
||||
|
||||
|
@ -121,20 +121,20 @@ def bug708901():
|
|||
pass
|
||||
|
||||
dis_bug708901 = """\
|
||||
%3d 0 SETUP_LOOP 23 (to 26)
|
||||
3 LOAD_GLOBAL 0 (range)
|
||||
6 LOAD_CONST 1 (1)
|
||||
%3d 0 SETUP_LOOP 18 (to 20)
|
||||
2 LOAD_GLOBAL 0 (range)
|
||||
4 LOAD_CONST 1 (1)
|
||||
|
||||
%3d 9 LOAD_CONST 2 (10)
|
||||
12 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
|
||||
15 GET_ITER
|
||||
>> 16 FOR_ITER 6 (to 25)
|
||||
19 STORE_FAST 0 (res)
|
||||
%3d 6 LOAD_CONST 2 (10)
|
||||
8 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
|
||||
10 GET_ITER
|
||||
>> 12 FOR_ITER 4 (to 18)
|
||||
14 STORE_FAST 0 (res)
|
||||
|
||||
%3d 22 JUMP_ABSOLUTE 16
|
||||
>> 25 POP_BLOCK
|
||||
>> 26 LOAD_CONST 0 (None)
|
||||
29 RETURN_VALUE
|
||||
%3d 16 JUMP_ABSOLUTE 12
|
||||
>> 18 POP_BLOCK
|
||||
>> 20 LOAD_CONST 0 (None)
|
||||
22 RETURN_VALUE
|
||||
""" % (bug708901.__code__.co_firstlineno + 1,
|
||||
bug708901.__code__.co_firstlineno + 2,
|
||||
bug708901.__code__.co_firstlineno + 3)
|
||||
|
@ -147,22 +147,22 @@ def bug1333982(x=[]):
|
|||
|
||||
dis_bug1333982 = """\
|
||||
%3d 0 LOAD_CONST 1 (0)
|
||||
3 POP_JUMP_IF_TRUE 35
|
||||
6 LOAD_GLOBAL 0 (AssertionError)
|
||||
9 LOAD_CONST 2 (<code object <listcomp> at 0x..., file "%s", line %d>)
|
||||
12 LOAD_CONST 3 ('bug1333982.<locals>.<listcomp>')
|
||||
15 MAKE_FUNCTION 0
|
||||
18 LOAD_FAST 0 (x)
|
||||
21 GET_ITER
|
||||
2 POP_JUMP_IF_TRUE 26
|
||||
4 LOAD_GLOBAL 0 (AssertionError)
|
||||
6 LOAD_CONST 2 (<code object <listcomp> at 0x..., file "%s", line %d>)
|
||||
8 LOAD_CONST 3 ('bug1333982.<locals>.<listcomp>')
|
||||
10 MAKE_FUNCTION 0
|
||||
12 LOAD_FAST 0 (x)
|
||||
14 GET_ITER
|
||||
16 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
|
||||
|
||||
%3d 18 LOAD_CONST 4 (1)
|
||||
20 BINARY_ADD
|
||||
22 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
|
||||
24 RAISE_VARARGS 1
|
||||
|
||||
%3d 25 LOAD_CONST 4 (1)
|
||||
28 BINARY_ADD
|
||||
29 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
|
||||
32 RAISE_VARARGS 1
|
||||
|
||||
%3d >> 35 LOAD_CONST 0 (None)
|
||||
38 RETURN_VALUE
|
||||
%3d >> 26 LOAD_CONST 0 (None)
|
||||
28 RETURN_VALUE
|
||||
""" % (bug1333982.__code__.co_firstlineno + 1,
|
||||
__file__,
|
||||
bug1333982.__code__.co_firstlineno + 1,
|
||||
|
@ -171,19 +171,19 @@ dis_bug1333982 = """\
|
|||
|
||||
_BIG_LINENO_FORMAT = """\
|
||||
%3d 0 LOAD_GLOBAL 0 (spam)
|
||||
3 POP_TOP
|
||||
2 POP_TOP
|
||||
4 LOAD_CONST 0 (None)
|
||||
7 RETURN_VALUE
|
||||
6 RETURN_VALUE
|
||||
"""
|
||||
|
||||
dis_module_expected_results = """\
|
||||
Disassembly of f:
|
||||
4 0 LOAD_CONST 0 (None)
|
||||
3 RETURN_VALUE
|
||||
2 RETURN_VALUE
|
||||
|
||||
Disassembly of g:
|
||||
5 0 LOAD_CONST 0 (None)
|
||||
3 RETURN_VALUE
|
||||
2 RETURN_VALUE
|
||||
|
||||
"""
|
||||
|
||||
|
@ -191,20 +191,20 @@ expr_str = "x + 1"
|
|||
|
||||
dis_expr_str = """\
|
||||
1 0 LOAD_NAME 0 (x)
|
||||
3 LOAD_CONST 0 (1)
|
||||
6 BINARY_ADD
|
||||
7 RETURN_VALUE
|
||||
2 LOAD_CONST 0 (1)
|
||||
4 BINARY_ADD
|
||||
6 RETURN_VALUE
|
||||
"""
|
||||
|
||||
simple_stmt_str = "x = x + 1"
|
||||
|
||||
dis_simple_stmt_str = """\
|
||||
1 0 LOAD_NAME 0 (x)
|
||||
3 LOAD_CONST 0 (1)
|
||||
6 BINARY_ADD
|
||||
7 STORE_NAME 0 (x)
|
||||
10 LOAD_CONST 1 (None)
|
||||
13 RETURN_VALUE
|
||||
2 LOAD_CONST 0 (1)
|
||||
4 BINARY_ADD
|
||||
6 STORE_NAME 0 (x)
|
||||
8 LOAD_CONST 1 (None)
|
||||
10 RETURN_VALUE
|
||||
"""
|
||||
|
||||
compound_stmt_str = """\
|
||||
|
@ -215,54 +215,54 @@ while 1:
|
|||
|
||||
dis_compound_stmt_str = """\
|
||||
1 0 LOAD_CONST 0 (0)
|
||||
3 STORE_NAME 0 (x)
|
||||
2 STORE_NAME 0 (x)
|
||||
|
||||
2 6 SETUP_LOOP 14 (to 23)
|
||||
2 4 SETUP_LOOP 12 (to 18)
|
||||
|
||||
3 >> 9 LOAD_NAME 0 (x)
|
||||
12 LOAD_CONST 1 (1)
|
||||
15 INPLACE_ADD
|
||||
16 STORE_NAME 0 (x)
|
||||
19 JUMP_ABSOLUTE 9
|
||||
22 POP_BLOCK
|
||||
>> 23 LOAD_CONST 2 (None)
|
||||
26 RETURN_VALUE
|
||||
3 >> 6 LOAD_NAME 0 (x)
|
||||
8 LOAD_CONST 1 (1)
|
||||
10 INPLACE_ADD
|
||||
12 STORE_NAME 0 (x)
|
||||
14 JUMP_ABSOLUTE 6
|
||||
16 POP_BLOCK
|
||||
>> 18 LOAD_CONST 2 (None)
|
||||
20 RETURN_VALUE
|
||||
"""
|
||||
|
||||
dis_traceback = """\
|
||||
%3d 0 SETUP_EXCEPT 12 (to 15)
|
||||
%3d 0 SETUP_EXCEPT 12 (to 14)
|
||||
|
||||
%3d 3 LOAD_CONST 1 (1)
|
||||
6 LOAD_CONST 2 (0)
|
||||
--> 9 BINARY_TRUE_DIVIDE
|
||||
10 POP_TOP
|
||||
11 POP_BLOCK
|
||||
12 JUMP_FORWARD 46 (to 61)
|
||||
%3d 2 LOAD_CONST 1 (1)
|
||||
4 LOAD_CONST 2 (0)
|
||||
--> 6 BINARY_TRUE_DIVIDE
|
||||
8 POP_TOP
|
||||
10 POP_BLOCK
|
||||
12 JUMP_FORWARD 40 (to 54)
|
||||
|
||||
%3d >> 15 DUP_TOP
|
||||
%3d >> 14 DUP_TOP
|
||||
16 LOAD_GLOBAL 0 (Exception)
|
||||
19 COMPARE_OP 10 (exception match)
|
||||
22 POP_JUMP_IF_FALSE 60
|
||||
25 POP_TOP
|
||||
26 STORE_FAST 0 (e)
|
||||
29 POP_TOP
|
||||
30 SETUP_FINALLY 14 (to 47)
|
||||
18 COMPARE_OP 10 (exception match)
|
||||
20 POP_JUMP_IF_FALSE 52
|
||||
22 POP_TOP
|
||||
24 STORE_FAST 0 (e)
|
||||
26 POP_TOP
|
||||
28 SETUP_FINALLY 12 (to 42)
|
||||
|
||||
%3d 33 LOAD_FAST 0 (e)
|
||||
36 LOAD_ATTR 1 (__traceback__)
|
||||
39 STORE_FAST 1 (tb)
|
||||
42 POP_BLOCK
|
||||
43 POP_EXCEPT
|
||||
44 LOAD_CONST 0 (None)
|
||||
>> 47 LOAD_CONST 0 (None)
|
||||
50 STORE_FAST 0 (e)
|
||||
53 DELETE_FAST 0 (e)
|
||||
56 END_FINALLY
|
||||
57 JUMP_FORWARD 1 (to 61)
|
||||
>> 60 END_FINALLY
|
||||
%3d 30 LOAD_FAST 0 (e)
|
||||
32 LOAD_ATTR 1 (__traceback__)
|
||||
34 STORE_FAST 1 (tb)
|
||||
36 POP_BLOCK
|
||||
38 POP_EXCEPT
|
||||
40 LOAD_CONST 0 (None)
|
||||
>> 42 LOAD_CONST 0 (None)
|
||||
44 STORE_FAST 0 (e)
|
||||
46 DELETE_FAST 0 (e)
|
||||
48 END_FINALLY
|
||||
50 JUMP_FORWARD 2 (to 54)
|
||||
>> 52 END_FINALLY
|
||||
|
||||
%3d >> 61 LOAD_FAST 1 (tb)
|
||||
64 RETURN_VALUE
|
||||
%3d >> 54 LOAD_FAST 1 (tb)
|
||||
56 RETURN_VALUE
|
||||
""" % (TRACEBACK_CODE.co_firstlineno + 1,
|
||||
TRACEBACK_CODE.co_firstlineno + 2,
|
||||
TRACEBACK_CODE.co_firstlineno + 3,
|
||||
|
@ -650,170 +650,170 @@ expected_jumpy_line = 1
|
|||
Instruction = dis.Instruction
|
||||
expected_opinfo_outer = [
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=3, argrepr='3', offset=0, starts_line=2, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=3, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=0, argval='a', argrepr='a', offset=6, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=1, argval='b', argrepr='b', offset=9, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='BUILD_TUPLE', opcode=102, arg=2, argval=2, argrepr='', offset=12, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=code_object_f, argrepr=repr(code_object_f), offset=15, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='outer.<locals>.f', argrepr="'outer.<locals>.f'", offset=18, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='MAKE_CLOSURE', opcode=134, arg=2, argval=2, argrepr='', offset=21, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='f', argrepr='f', offset=24, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=27, starts_line=7, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=0, argval='a', argrepr='a', offset=30, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=1, argval='b', argrepr='b', offset=33, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval='', argrepr="''", offset=36, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval=1, argrepr='1', offset=39, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=42, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=45, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval='Hello world!', argrepr="'Hello world!'", offset=48, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=7, argval=7, argrepr='7 positional, 0 keyword pair', offset=51, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=54, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=55, starts_line=8, is_jump_target=False),
|
||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=58, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=2, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=0, argval='a', argrepr='a', offset=4, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=1, argval='b', argrepr='b', offset=6, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='BUILD_TUPLE', opcode=102, arg=2, argval=2, argrepr='', offset=8, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=code_object_f, argrepr=repr(code_object_f), offset=10, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='outer.<locals>.f', argrepr="'outer.<locals>.f'", offset=12, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='MAKE_CLOSURE', opcode=134, arg=2, argval=2, argrepr='', offset=14, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='f', argrepr='f', offset=16, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=18, starts_line=7, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=0, argval='a', argrepr='a', offset=20, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=1, argval='b', argrepr='b', offset=22, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval='', argrepr="''", offset=24, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval=1, argrepr='1', offset=26, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=28, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=30, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval='Hello world!', argrepr="'Hello world!'", offset=32, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=7, argval=7, argrepr='7 positional, 0 keyword pair', offset=34, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=36, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=38, starts_line=8, is_jump_target=False),
|
||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=40, starts_line=None, is_jump_target=False),
|
||||
]
|
||||
|
||||
expected_opinfo_f = [
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=5, argrepr='5', offset=0, starts_line=3, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=6, argrepr='6', offset=3, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=2, argval='a', argrepr='a', offset=6, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=3, argval='b', argrepr='b', offset=9, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=0, argval='c', argrepr='c', offset=12, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=1, argval='d', argrepr='d', offset=15, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='BUILD_TUPLE', opcode=102, arg=4, argval=4, argrepr='', offset=18, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=code_object_inner, argrepr=repr(code_object_inner), offset=21, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='outer.<locals>.f.<locals>.inner', argrepr="'outer.<locals>.f.<locals>.inner'", offset=24, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='MAKE_CLOSURE', opcode=134, arg=2, argval=2, argrepr='', offset=27, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='inner', argrepr='inner', offset=30, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=33, starts_line=5, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=2, argval='a', argrepr='a', offset=36, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=3, argval='b', argrepr='b', offset=39, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=0, argval='c', argrepr='c', offset=42, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=1, argval='d', argrepr='d', offset=45, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=4, argval=4, argrepr='4 positional, 0 keyword pair', offset=48, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=51, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=52, starts_line=6, is_jump_target=False),
|
||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=55, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=6, argrepr='6', offset=2, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=2, argval='a', argrepr='a', offset=4, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=3, argval='b', argrepr='b', offset=6, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=0, argval='c', argrepr='c', offset=8, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=1, argval='d', argrepr='d', offset=10, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='BUILD_TUPLE', opcode=102, arg=4, argval=4, argrepr='', offset=12, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=code_object_inner, argrepr=repr(code_object_inner), offset=14, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='outer.<locals>.f.<locals>.inner', argrepr="'outer.<locals>.f.<locals>.inner'", offset=16, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='MAKE_CLOSURE', opcode=134, arg=2, argval=2, argrepr='', offset=18, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='inner', argrepr='inner', offset=20, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=22, starts_line=5, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=2, argval='a', argrepr='a', offset=24, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=3, argval='b', argrepr='b', offset=26, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=0, argval='c', argrepr='c', offset=28, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=1, argval='d', argrepr='d', offset=30, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=4, argval=4, argrepr='4 positional, 0 keyword pair', offset=32, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=34, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=36, starts_line=6, is_jump_target=False),
|
||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=38, starts_line=None, is_jump_target=False),
|
||||
]
|
||||
|
||||
expected_opinfo_inner = [
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=0, starts_line=4, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=0, argval='a', argrepr='a', offset=3, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=1, argval='b', argrepr='b', offset=6, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=2, argval='c', argrepr='c', offset=9, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=3, argval='d', argrepr='d', offset=12, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='e', argrepr='e', offset=15, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=18, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=6, argval=6, argrepr='6 positional, 0 keyword pair', offset=21, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=24, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=25, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=28, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=0, argval='a', argrepr='a', offset=2, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=1, argval='b', argrepr='b', offset=4, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=2, argval='c', argrepr='c', offset=6, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_DEREF', opcode=136, arg=3, argval='d', argrepr='d', offset=8, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='e', argrepr='e', offset=10, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=12, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=6, argval=6, argrepr='6 positional, 0 keyword pair', offset=14, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=16, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=18, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=20, starts_line=None, is_jump_target=False),
|
||||
]
|
||||
|
||||
expected_opinfo_jumpy = [
|
||||
Instruction(opname='SETUP_LOOP', opcode=120, arg=68, argval=71, argrepr='to 71', offset=0, starts_line=3, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='range', argrepr='range', offset=3, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=6, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=9, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=12, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='FOR_ITER', opcode=93, arg=44, argval=60, argrepr='to 60', offset=13, starts_line=None, is_jump_target=True),
|
||||
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=16, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=19, starts_line=4, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=22, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=25, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=28, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=29, starts_line=5, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=32, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=35, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=44, argval=44, argrepr='', offset=38, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=13, argval=13, argrepr='', offset=41, starts_line=6, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=44, starts_line=7, is_jump_target=True),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=47, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=50, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=13, argval=13, argrepr='', offset=53, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='BREAK_LOOP', opcode=80, arg=None, argval=None, argrepr='', offset=56, starts_line=8, is_jump_target=False),
|
||||
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=13, argval=13, argrepr='', offset=57, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=60, starts_line=None, is_jump_target=True),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=61, starts_line=10, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=64, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=67, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=70, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='SETUP_LOOP', opcode=120, arg=68, argval=142, argrepr='to 142', offset=71, starts_line=11, is_jump_target=True),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=74, starts_line=None, is_jump_target=True),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=131, argval=131, argrepr='', offset=77, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=80, starts_line=12, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=83, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=86, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=89, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=90, starts_line=13, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=93, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='INPLACE_SUBTRACT', opcode=56, arg=None, argval=None, argrepr='', offset=96, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=97, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=100, starts_line=14, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=103, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=106, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=115, argval=115, argrepr='', offset=109, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=74, argval=74, argrepr='', offset=112, starts_line=15, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=115, starts_line=16, is_jump_target=True),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=118, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=121, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=74, argval=74, argrepr='', offset=124, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='BREAK_LOOP', opcode=80, arg=None, argval=None, argrepr='', offset=127, starts_line=17, is_jump_target=False),
|
||||
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=74, argval=74, argrepr='', offset=128, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=131, starts_line=None, is_jump_target=True),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=132, starts_line=19, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=135, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=138, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=141, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='SETUP_FINALLY', opcode=122, arg=73, argval=218, argrepr='to 218', offset=142, starts_line=20, is_jump_target=True),
|
||||
Instruction(opname='SETUP_EXCEPT', opcode=121, arg=12, argval=160, argrepr='to 160', offset=145, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=148, starts_line=21, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=151, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=154, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=155, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=156, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=28, argval=188, argrepr='to 188', offset=157, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=160, starts_line=22, is_jump_target=True),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=161, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='COMPARE_OP', opcode=107, arg=10, argval='exception match', argrepr='exception match', offset=164, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=187, argval=187, argrepr='', offset=167, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=171, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=173, starts_line=23, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=176, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=179, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=183, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=27, argval=214, argrepr='to 214', offset=184, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=187, starts_line=None, is_jump_target=True),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=188, starts_line=25, is_jump_target=True),
|
||||
Instruction(opname='SETUP_WITH', opcode=143, arg=17, argval=211, argrepr='to 211', offset=191, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=194, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=197, starts_line=26, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=200, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=203, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=206, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=207, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=208, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='WITH_CLEANUP_START', opcode=81, arg=None, argval=None, argrepr='', offset=211, starts_line=None, is_jump_target=True),
|
||||
Instruction(opname='WITH_CLEANUP_FINISH', opcode=82, arg=None, argval=None, argrepr='', offset=212, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=213, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=214, starts_line=None, is_jump_target=True),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=215, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=218, starts_line=28, is_jump_target=True),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=221, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=224, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=227, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=228, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=229, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=232, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='SETUP_LOOP', opcode=120, arg=52, argval=54, argrepr='to 54', offset=0, starts_line=3, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='range', argrepr='range', offset=2, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=4, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=6, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=8, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='FOR_ITER', opcode=93, arg=32, argval=44, argrepr='to 44', offset=10, starts_line=None, is_jump_target=True),
|
||||
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=12, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=14, starts_line=4, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=16, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=18, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=20, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=22, starts_line=5, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=24, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=26, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=32, argval=32, argrepr='', offset=28, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=10, argval=10, argrepr='', offset=30, starts_line=6, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=32, starts_line=7, is_jump_target=True),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=34, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=36, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=10, argval=10, argrepr='', offset=38, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='BREAK_LOOP', opcode=80, arg=None, argval=None, argrepr='', offset=40, starts_line=8, is_jump_target=False),
|
||||
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=10, argval=10, argrepr='', offset=42, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=44, starts_line=None, is_jump_target=True),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=46, starts_line=10, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=48, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=50, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=52, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='SETUP_LOOP', opcode=120, arg=52, argval=108, argrepr='to 108', offset=54, starts_line=11, is_jump_target=True),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=56, starts_line=None, is_jump_target=True),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=98, argval=98, argrepr='', offset=58, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=60, starts_line=12, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=62, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=64, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=66, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=68, starts_line=13, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=70, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='INPLACE_SUBTRACT', opcode=56, arg=None, argval=None, argrepr='', offset=72, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=74, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=76, starts_line=14, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=78, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=80, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=86, argval=86, argrepr='', offset=82, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=56, argval=56, argrepr='', offset=84, starts_line=15, is_jump_target=False),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=86, starts_line=16, is_jump_target=True),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=88, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=90, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=56, argval=56, argrepr='', offset=92, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='BREAK_LOOP', opcode=80, arg=None, argval=None, argrepr='', offset=94, starts_line=17, is_jump_target=False),
|
||||
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=56, argval=56, argrepr='', offset=96, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=98, starts_line=None, is_jump_target=True),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=100, starts_line=19, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=102, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=104, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=106, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='SETUP_FINALLY', opcode=122, arg=70, argval=180, argrepr='to 180', offset=108, starts_line=20, is_jump_target=True),
|
||||
Instruction(opname='SETUP_EXCEPT', opcode=121, arg=12, argval=124, argrepr='to 124', offset=110, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=112, starts_line=21, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=114, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=116, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=118, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=120, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=28, argval=152, argrepr='to 152', offset=122, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=124, starts_line=22, is_jump_target=True),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=126, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='COMPARE_OP', opcode=107, arg=10, argval='exception match', argrepr='exception match', offset=128, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=150, argval=150, argrepr='', offset=130, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=132, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=134, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=136, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=138, starts_line=23, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=140, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=142, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=146, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=26, argval=176, argrepr='to 176', offset=148, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=150, starts_line=None, is_jump_target=True),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=152, starts_line=25, is_jump_target=True),
|
||||
Instruction(opname='SETUP_WITH', opcode=143, arg=14, argval=170, argrepr='to 170', offset=154, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=156, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=158, starts_line=26, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=160, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=162, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=168, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='WITH_CLEANUP_START', opcode=81, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=True),
|
||||
Instruction(opname='WITH_CLEANUP_FINISH', opcode=82, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=174, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=176, starts_line=None, is_jump_target=True),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=178, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=180, starts_line=28, is_jump_target=True),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=182, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=184, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=190, starts_line=None, is_jump_target=False),
|
||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=192, starts_line=None, is_jump_target=False),
|
||||
]
|
||||
|
||||
# One last piece of inspect fodder to check the default line number handling
|
||||
def simple(): pass
|
||||
expected_opinfo_simple = [
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=0, starts_line=simple.__code__.co_firstlineno, is_jump_target=False),
|
||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=3, starts_line=None, is_jump_target=False)
|
||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=2, starts_line=None, is_jump_target=False)
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -10,6 +10,9 @@ What's New in Python 3.6.0 alpha 2
|
|||
Core and Builtins
|
||||
-----------------
|
||||
|
||||
- Issue #26647: Python interpreter now uses 16-bit wordcode instead of bytecode.
|
||||
Patch by Demur Rumed.
|
||||
|
||||
- Issue #23275: Allow assigning to an empty target list in round brackets:
|
||||
() = iterable.
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
|
|||
memset(blockstack, '\0', sizeof(blockstack));
|
||||
memset(in_finally, '\0', sizeof(in_finally));
|
||||
blockstack_top = 0;
|
||||
for (addr = 0; addr < code_len; addr++) {
|
||||
for (addr = 0; addr < code_len; addr += 2) {
|
||||
unsigned char op = code[addr];
|
||||
switch (op) {
|
||||
case SETUP_LOOP:
|
||||
|
@ -251,10 +251,6 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (op >= HAVE_ARGUMENT) {
|
||||
addr += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify that the blockstack tracking code didn't get lost. */
|
||||
|
@ -277,7 +273,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
|
|||
* can tell whether the jump goes into any blocks without coming out
|
||||
* again - in that case we raise an exception below. */
|
||||
delta_iblock = 0;
|
||||
for (addr = min_addr; addr < max_addr; addr++) {
|
||||
for (addr = min_addr; addr < max_addr; addr += 2) {
|
||||
unsigned char op = code[addr];
|
||||
switch (op) {
|
||||
case SETUP_LOOP:
|
||||
|
@ -294,10 +290,6 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
|
|||
}
|
||||
|
||||
min_delta_iblock = Py_MIN(min_delta_iblock, delta_iblock);
|
||||
|
||||
if (op >= HAVE_ARGUMENT) {
|
||||
addr += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Derive the absolute iblock values from the deltas. */
|
||||
|
|
|
@ -277,7 +277,7 @@ _PyGen_yf(PyGenObject *gen)
|
|||
PyObject *bytecode = f->f_code->co_code;
|
||||
unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode);
|
||||
|
||||
if (code[f->f_lasti + 1] != YIELD_FROM)
|
||||
if (code[f->f_lasti + 2] != YIELD_FROM)
|
||||
return NULL;
|
||||
yf = f->f_stacktop[-1];
|
||||
Py_INCREF(yf);
|
||||
|
@ -376,7 +376,7 @@ gen_throw(PyGenObject *gen, PyObject *args)
|
|||
assert(ret == yf);
|
||||
Py_DECREF(ret);
|
||||
/* Termination repetition of YIELD_FROM */
|
||||
gen->gi_frame->f_lasti++;
|
||||
gen->gi_frame->f_lasti += 2;
|
||||
if (_PyGen_FetchStopIterationValue(&val) == 0) {
|
||||
ret = gen_send_ex(gen, val, 0, 0);
|
||||
Py_DECREF(val);
|
||||
|
|
|
@ -1089,7 +1089,7 @@ static PYC_MAGIC magic_values[] = {
|
|||
{ 3190, 3230, L"3.3" },
|
||||
{ 3250, 3310, L"3.4" },
|
||||
{ 3320, 3350, L"3.5" },
|
||||
{ 3360, 3361, L"3.6" },
|
||||
{ 3360, 3370, L"3.6" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -209,6 +209,7 @@
|
|||
<ClInclude Include="..\Python\condvar.h" />
|
||||
<ClInclude Include="..\Python\importdl.h" />
|
||||
<ClInclude Include="..\Python\thread_nt.h" />
|
||||
<ClInclude Include="..\Python\wordcode_helpers.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\Modules\_bisectmodule.c" />
|
||||
|
|
|
@ -420,6 +420,9 @@
|
|||
<ClInclude Include="..\Python\thread_nt.h">
|
||||
<Filter>Python</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Python\wordcode_helpers.h">
|
||||
<Filter>Python</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Python\condvar.h">
|
||||
<Filter>Python</Filter>
|
||||
</ClInclude>
|
||||
|
|
129
Python/ceval.c
129
Python/ceval.c
|
@ -886,24 +886,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
/* Import the static jump table */
|
||||
#include "opcode_targets.h"
|
||||
|
||||
/* This macro is used when several opcodes defer to the same implementation
|
||||
(e.g. SETUP_LOOP, SETUP_FINALLY) */
|
||||
#define TARGET_WITH_IMPL(op, impl) \
|
||||
TARGET_##op: \
|
||||
opcode = op; \
|
||||
if (HAS_ARG(op)) \
|
||||
oparg = NEXTARG(); \
|
||||
case op: \
|
||||
goto impl; \
|
||||
|
||||
#define TARGET(op) \
|
||||
TARGET_##op: \
|
||||
opcode = op; \
|
||||
if (HAS_ARG(op)) \
|
||||
oparg = NEXTARG(); \
|
||||
case op:
|
||||
|
||||
|
||||
#define DISPATCH() \
|
||||
{ \
|
||||
if (!_Py_atomic_load_relaxed(&eval_breaker)) { \
|
||||
|
@ -917,7 +903,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
{ \
|
||||
if (!lltrace && !_Py_TracingPossible) { \
|
||||
f->f_lasti = INSTR_OFFSET(); \
|
||||
goto *opcode_targets[*next_instr++]; \
|
||||
opcode = NEXTOP(); \
|
||||
oparg = NEXTARG(); \
|
||||
goto *opcode_targets[opcode]; \
|
||||
} \
|
||||
goto fast_next_opcode; \
|
||||
}
|
||||
|
@ -926,7 +914,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
{ \
|
||||
if (!_Py_TracingPossible) { \
|
||||
f->f_lasti = INSTR_OFFSET(); \
|
||||
goto *opcode_targets[*next_instr++]; \
|
||||
opcode = NEXTOP(); \
|
||||
oparg = NEXTARG(); \
|
||||
goto *opcode_targets[opcode]; \
|
||||
} \
|
||||
goto fast_next_opcode; \
|
||||
}
|
||||
|
@ -935,10 +925,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
#else
|
||||
#define TARGET(op) \
|
||||
case op:
|
||||
#define TARGET_WITH_IMPL(op, impl) \
|
||||
/* silence compiler warnings about `impl` unused */ \
|
||||
if (0) goto impl; \
|
||||
case op:
|
||||
|
||||
#define DISPATCH() continue
|
||||
#define FAST_DISPATCH() goto fast_next_opcode
|
||||
#endif
|
||||
|
@ -995,9 +982,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
/* Code access macros */
|
||||
|
||||
#define INSTR_OFFSET() ((int)(next_instr - first_instr))
|
||||
#define NEXTOP() (*next_instr++)
|
||||
#define NEXTARG() (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2])
|
||||
#define PEEKARG() ((next_instr[2]<<8) + next_instr[1])
|
||||
#define NEXTOP() (next_instr+=2, next_instr[-2])
|
||||
#define NEXTARG() (next_instr[-1])
|
||||
#define PEEKARG() (next_instr[1])
|
||||
#define JUMPTO(x) (next_instr = first_instr + (x))
|
||||
#define JUMPBY(x) (next_instr += (x))
|
||||
|
||||
|
@ -1012,10 +999,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
processor's own internal branch predication has a high likelihood of
|
||||
success, resulting in a nearly zero-overhead transition to the
|
||||
next opcode. A successful prediction saves a trip through the eval-loop
|
||||
including its two unpredictable branches, the HAS_ARG test and the
|
||||
switch-case. Combined with the processor's internal branch prediction,
|
||||
a successful PREDICT has the effect of making the two opcodes run as if
|
||||
they were a single new opcode with the bodies combined.
|
||||
including its unpredictable switch-case branch. Combined with the
|
||||
processor's internal branch prediction, a successful PREDICT has the
|
||||
effect of making the two opcodes run as if they were a single new opcode
|
||||
with the bodies combined.
|
||||
|
||||
If collecting opcode statistics, your choices are to either keep the
|
||||
predictions turned-on and interpret the results as if some opcodes
|
||||
|
@ -1030,13 +1017,18 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
|
||||
#if defined(DYNAMIC_EXECUTION_PROFILE) || USE_COMPUTED_GOTOS
|
||||
#define PREDICT(op) if (0) goto PRED_##op
|
||||
#define PREDICTED(op) PRED_##op:
|
||||
#define PREDICTED_WITH_ARG(op) PRED_##op:
|
||||
#else
|
||||
#define PREDICT(op) if (*next_instr == op) goto PRED_##op
|
||||
#define PREDICTED(op) PRED_##op: next_instr++
|
||||
#define PREDICTED_WITH_ARG(op) PRED_##op: oparg = PEEKARG(); next_instr += 3
|
||||
#define PREDICT(op) \
|
||||
do{ \
|
||||
if (*next_instr == op){ \
|
||||
opcode = op; \
|
||||
oparg = PEEKARG(); \
|
||||
next_instr += 2; \
|
||||
goto PRED_##op; \
|
||||
} \
|
||||
} while(0)
|
||||
#endif
|
||||
#define PREDICTED(op) PRED_##op:
|
||||
|
||||
|
||||
/* Stack manipulation macros */
|
||||
|
@ -1100,7 +1092,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
}
|
||||
|
||||
#define UNWIND_EXCEPT_HANDLER(b) \
|
||||
{ \
|
||||
do { \
|
||||
PyObject *type, *value, *traceback; \
|
||||
assert(STACK_LEVEL() >= (b)->b_level + 3); \
|
||||
while (STACK_LEVEL() > (b)->b_level + 3) { \
|
||||
|
@ -1116,7 +1108,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
Py_XDECREF(type); \
|
||||
Py_XDECREF(value); \
|
||||
Py_XDECREF(traceback); \
|
||||
}
|
||||
} while(0)
|
||||
|
||||
/* Start of code */
|
||||
|
||||
|
@ -1166,15 +1158,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
fastlocals = f->f_localsplus;
|
||||
freevars = f->f_localsplus + co->co_nlocals;
|
||||
first_instr = (unsigned char*) PyBytes_AS_STRING(co->co_code);
|
||||
/* An explanation is in order for the next line.
|
||||
/*
|
||||
f->f_lasti refers to the index of the last instruction,
|
||||
unless it's -1 in which case next_instr should be first_instr.
|
||||
|
||||
f->f_lasti now refers to the index of the last instruction
|
||||
executed. You might think this was obvious from the name, but
|
||||
this wasn't always true before 2.3! PyFrame_New now sets
|
||||
f->f_lasti to -1 (i.e. the index *before* the first instruction)
|
||||
and YIELD_VALUE doesn't fiddle with f_lasti any more. So this
|
||||
does work. Promise.
|
||||
YIELD_FROM sets f_lasti to itself, in order to repeated yield
|
||||
YIELD_FROM sets f_lasti to itself, in order to repeatedly yield
|
||||
multiple values.
|
||||
|
||||
When the PREDICT() macros are enabled, some opcode pairs follow in
|
||||
|
@ -1183,9 +1171,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
were a single new opcode; accordingly,f->f_lasti will point to
|
||||
the first code in the pair (for instance, GET_ITER followed by
|
||||
FOR_ITER is effectively a single opcode and f->f_lasti will point
|
||||
at to the beginning of the combined pair.)
|
||||
to the beginning of the combined pair.)
|
||||
*/
|
||||
next_instr = first_instr + f->f_lasti + 1;
|
||||
next_instr = first_instr;
|
||||
if (f->f_lasti >= 0) {
|
||||
next_instr += f->f_lasti + 2;
|
||||
}
|
||||
stack_pointer = f->f_stacktop;
|
||||
assert(stack_pointer != NULL);
|
||||
f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */
|
||||
|
@ -1323,10 +1314,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
/* Extract opcode and argument */
|
||||
|
||||
opcode = NEXTOP();
|
||||
oparg = 0; /* allows oparg to be stored in a register because
|
||||
it doesn't have to be remembered across a full loop */
|
||||
if (HAS_ARG(opcode))
|
||||
oparg = NEXTARG();
|
||||
oparg = NEXTARG();
|
||||
dispatch_opcode:
|
||||
#ifdef DYNAMIC_EXECUTION_PROFILE
|
||||
#ifdef DXPAIRS
|
||||
|
@ -1384,7 +1372,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
FAST_DISPATCH();
|
||||
}
|
||||
|
||||
PREDICTED_WITH_ARG(STORE_FAST);
|
||||
PREDICTED(STORE_FAST);
|
||||
TARGET(STORE_FAST) {
|
||||
PyObject *value = POP();
|
||||
SETLOCAL(oparg, value);
|
||||
|
@ -2075,7 +2063,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
f->f_stacktop = stack_pointer;
|
||||
why = WHY_YIELD;
|
||||
/* and repeat... */
|
||||
f->f_lasti--;
|
||||
f->f_lasti -= 2;
|
||||
goto fast_yield;
|
||||
}
|
||||
|
||||
|
@ -2213,7 +2201,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
PREDICTED_WITH_ARG(UNPACK_SEQUENCE);
|
||||
PREDICTED(UNPACK_SEQUENCE);
|
||||
TARGET(UNPACK_SEQUENCE) {
|
||||
PyObject *seq = POP(), *item, **items;
|
||||
if (PyTuple_CheckExact(seq) &&
|
||||
|
@ -2511,9 +2499,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET_WITH_IMPL(BUILD_TUPLE_UNPACK, _build_list_unpack)
|
||||
TARGET(BUILD_LIST_UNPACK)
|
||||
_build_list_unpack: {
|
||||
TARGET(BUILD_TUPLE_UNPACK)
|
||||
TARGET(BUILD_LIST_UNPACK) {
|
||||
int convert_to_tuple = opcode == BUILD_TUPLE_UNPACK;
|
||||
int i;
|
||||
PyObject *sum = PyList_New(0);
|
||||
|
@ -2610,9 +2597,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET_WITH_IMPL(BUILD_MAP_UNPACK_WITH_CALL, _build_map_unpack)
|
||||
TARGET(BUILD_MAP_UNPACK)
|
||||
_build_map_unpack: {
|
||||
TARGET(BUILD_MAP_UNPACK_WITH_CALL)
|
||||
TARGET(BUILD_MAP_UNPACK) {
|
||||
int with_call = opcode == BUILD_MAP_UNPACK_WITH_CALL;
|
||||
int num_maps;
|
||||
int function_location;
|
||||
|
@ -2819,7 +2805,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
FAST_DISPATCH();
|
||||
}
|
||||
|
||||
PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE);
|
||||
PREDICTED(POP_JUMP_IF_FALSE);
|
||||
TARGET(POP_JUMP_IF_FALSE) {
|
||||
PyObject *cond = POP();
|
||||
int err;
|
||||
|
@ -2843,7 +2829,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE);
|
||||
PREDICTED(POP_JUMP_IF_TRUE);
|
||||
TARGET(POP_JUMP_IF_TRUE) {
|
||||
PyObject *cond = POP();
|
||||
int err;
|
||||
|
@ -2920,7 +2906,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
PREDICTED_WITH_ARG(JUMP_ABSOLUTE);
|
||||
PREDICTED(JUMP_ABSOLUTE);
|
||||
TARGET(JUMP_ABSOLUTE) {
|
||||
JUMPTO(oparg);
|
||||
#if FAST_LOOPS
|
||||
|
@ -2977,7 +2963,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
PREDICTED_WITH_ARG(FOR_ITER);
|
||||
PREDICTED(FOR_ITER);
|
||||
TARGET(FOR_ITER) {
|
||||
/* before: [iter]; after: [iter, iter()] *or* [] */
|
||||
PyObject *iter = TOP();
|
||||
|
@ -3015,10 +3001,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
goto fast_block_end;
|
||||
}
|
||||
|
||||
TARGET_WITH_IMPL(SETUP_LOOP, _setup_finally)
|
||||
TARGET_WITH_IMPL(SETUP_EXCEPT, _setup_finally)
|
||||
TARGET(SETUP_FINALLY)
|
||||
_setup_finally: {
|
||||
TARGET(SETUP_LOOP)
|
||||
TARGET(SETUP_EXCEPT)
|
||||
TARGET(SETUP_FINALLY) {
|
||||
/* NOTE: If you add any new block-setup opcodes that
|
||||
are not try/except/finally handlers, you may need
|
||||
to update the PyGen_NeedsFinalizing() function.
|
||||
|
@ -3213,10 +3198,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET_WITH_IMPL(CALL_FUNCTION_VAR, _call_function_var_kw)
|
||||
TARGET_WITH_IMPL(CALL_FUNCTION_KW, _call_function_var_kw)
|
||||
TARGET(CALL_FUNCTION_VAR_KW)
|
||||
_call_function_var_kw: {
|
||||
TARGET(CALL_FUNCTION_VAR)
|
||||
TARGET(CALL_FUNCTION_KW)
|
||||
TARGET(CALL_FUNCTION_VAR_KW) {
|
||||
int na = oparg & 0xff;
|
||||
int nk = (oparg>>8) & 0xff;
|
||||
int flags = (opcode - CALL_FUNCTION) & 3;
|
||||
|
@ -3258,9 +3242,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET_WITH_IMPL(MAKE_CLOSURE, _make_function)
|
||||
TARGET(MAKE_FUNCTION)
|
||||
_make_function: {
|
||||
TARGET(MAKE_CLOSURE)
|
||||
TARGET(MAKE_FUNCTION) {
|
||||
int posdefaults = oparg & 0xff;
|
||||
int kwdefaults = (oparg>>8) & 0xff;
|
||||
int num_annotations = (oparg >> 16) & 0x7fff;
|
||||
|
@ -3450,7 +3433,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
|
||||
TARGET(EXTENDED_ARG) {
|
||||
opcode = NEXTOP();
|
||||
oparg = oparg<<16 | NEXTARG();
|
||||
oparg = oparg<<8 | NEXTARG();
|
||||
goto dispatch_opcode;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "code.h"
|
||||
#include "symtable.h"
|
||||
#include "opcode.h"
|
||||
#include "wordcode_helpers.h"
|
||||
|
||||
#define DEFAULT_BLOCK_SIZE 16
|
||||
#define DEFAULT_BLOCKS 8
|
||||
|
@ -43,7 +44,6 @@
|
|||
struct instr {
|
||||
unsigned i_jabs : 1;
|
||||
unsigned i_jrel : 1;
|
||||
unsigned i_hasarg : 1;
|
||||
unsigned char i_opcode;
|
||||
int i_oparg;
|
||||
struct basicblock_ *i_target; /* target block (if jump instruction) */
|
||||
|
@ -1080,13 +1080,14 @@ compiler_addop(struct compiler *c, int opcode)
|
|||
basicblock *b;
|
||||
struct instr *i;
|
||||
int off;
|
||||
assert(!HAS_ARG(opcode));
|
||||
off = compiler_next_instr(c, c->u->u_curblock);
|
||||
if (off < 0)
|
||||
return 0;
|
||||
b = c->u->u_curblock;
|
||||
i = &b->b_instr[off];
|
||||
i->i_opcode = opcode;
|
||||
i->i_hasarg = 0;
|
||||
i->i_oparg = 0;
|
||||
if (opcode == RETURN_VALUE)
|
||||
b->b_return = 1;
|
||||
compiler_set_lineno(c, off);
|
||||
|
@ -1168,8 +1169,9 @@ compiler_addop_i(struct compiler *c, int opcode, Py_ssize_t oparg)
|
|||
|
||||
Limit to 32-bit signed C int (rather than INT_MAX) for portability.
|
||||
|
||||
The argument of a concrete bytecode instruction is limited to 16-bit.
|
||||
EXTENDED_ARG is used for 32-bit arguments. */
|
||||
The argument of a concrete bytecode instruction is limited to 8-bit.
|
||||
EXTENDED_ARG is used for 16, 24, and 32-bit arguments. */
|
||||
assert(HAS_ARG(opcode));
|
||||
assert(0 <= oparg && oparg <= 2147483647);
|
||||
|
||||
off = compiler_next_instr(c, c->u->u_curblock);
|
||||
|
@ -1178,7 +1180,6 @@ compiler_addop_i(struct compiler *c, int opcode, Py_ssize_t oparg)
|
|||
i = &c->u->u_curblock->b_instr[off];
|
||||
i->i_opcode = opcode;
|
||||
i->i_oparg = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int);
|
||||
i->i_hasarg = 1;
|
||||
compiler_set_lineno(c, off);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1189,6 +1190,7 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
|
|||
struct instr *i;
|
||||
int off;
|
||||
|
||||
assert(HAS_ARG(opcode));
|
||||
assert(b != NULL);
|
||||
off = compiler_next_instr(c, c->u->u_curblock);
|
||||
if (off < 0)
|
||||
|
@ -1196,7 +1198,6 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
|
|||
i = &c->u->u_curblock->b_instr[off];
|
||||
i->i_opcode = opcode;
|
||||
i->i_target = b;
|
||||
i->i_hasarg = 1;
|
||||
if (absolute)
|
||||
i->i_jabs = 1;
|
||||
else
|
||||
|
@ -4397,18 +4398,6 @@ assemble_free(struct assembler *a)
|
|||
PyObject_Free(a->a_postorder);
|
||||
}
|
||||
|
||||
/* Return the size of a basic block in bytes. */
|
||||
|
||||
static int
|
||||
instrsize(struct instr *instr)
|
||||
{
|
||||
if (!instr->i_hasarg)
|
||||
return 1; /* 1 byte for the opcode*/
|
||||
if (instr->i_oparg > 0xffff)
|
||||
return 6; /* 1 (opcode) + 1 (EXTENDED_ARG opcode) + 2 (oparg) + 2(oparg extended) */
|
||||
return 3; /* 1 (opcode) + 2 (oparg) */
|
||||
}
|
||||
|
||||
static int
|
||||
blocksize(basicblock *b)
|
||||
{
|
||||
|
@ -4416,7 +4405,7 @@ blocksize(basicblock *b)
|
|||
int size = 0;
|
||||
|
||||
for (i = 0; i < b->b_iused; i++)
|
||||
size += instrsize(&b->b_instr[i]);
|
||||
size += instrsize(b->b_instr[i].i_oparg);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -4536,15 +4525,12 @@ assemble_lnotab(struct assembler *a, struct instr *i)
|
|||
static int
|
||||
assemble_emit(struct assembler *a, struct instr *i)
|
||||
{
|
||||
int size, arg = 0, ext = 0;
|
||||
int size, arg = 0;
|
||||
Py_ssize_t len = PyBytes_GET_SIZE(a->a_bytecode);
|
||||
char *code;
|
||||
|
||||
size = instrsize(i);
|
||||
if (i->i_hasarg) {
|
||||
arg = i->i_oparg;
|
||||
ext = arg >> 16;
|
||||
}
|
||||
arg = i->i_oparg;
|
||||
size = instrsize(arg);
|
||||
if (i->i_lineno && !assemble_lnotab(a, i))
|
||||
return 0;
|
||||
if (a->a_offset + size >= len) {
|
||||
|
@ -4555,19 +4541,7 @@ assemble_emit(struct assembler *a, struct instr *i)
|
|||
}
|
||||
code = PyBytes_AS_STRING(a->a_bytecode) + a->a_offset;
|
||||
a->a_offset += size;
|
||||
if (size == 6) {
|
||||
assert(i->i_hasarg);
|
||||
*code++ = (char)EXTENDED_ARG;
|
||||
*code++ = ext & 0xff;
|
||||
*code++ = ext >> 8;
|
||||
arg &= 0xffff;
|
||||
}
|
||||
*code++ = i->i_opcode;
|
||||
if (i->i_hasarg) {
|
||||
assert(size == 3 || size == 6);
|
||||
*code++ = arg & 0xff;
|
||||
*code++ = arg >> 8;
|
||||
}
|
||||
write_op_arg((unsigned char*)code, i->i_opcode, arg, size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -4575,7 +4549,7 @@ static void
|
|||
assemble_jump_offsets(struct assembler *a, struct compiler *c)
|
||||
{
|
||||
basicblock *b;
|
||||
int bsize, totsize, extended_arg_count = 0, last_extended_arg_count;
|
||||
int bsize, totsize, extended_arg_recompile;
|
||||
int i;
|
||||
|
||||
/* Compute the size of each block and fixup jump args.
|
||||
|
@ -4588,27 +4562,26 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c)
|
|||
b->b_offset = totsize;
|
||||
totsize += bsize;
|
||||
}
|
||||
last_extended_arg_count = extended_arg_count;
|
||||
extended_arg_count = 0;
|
||||
extended_arg_recompile = 0;
|
||||
for (b = c->u->u_blocks; b != NULL; b = b->b_list) {
|
||||
bsize = b->b_offset;
|
||||
for (i = 0; i < b->b_iused; i++) {
|
||||
struct instr *instr = &b->b_instr[i];
|
||||
int isize = instrsize(instr->i_oparg);
|
||||
/* Relative jumps are computed relative to
|
||||
the instruction pointer after fetching
|
||||
the jump instruction.
|
||||
*/
|
||||
bsize += instrsize(instr);
|
||||
if (instr->i_jabs)
|
||||
bsize += isize;
|
||||
if (instr->i_jabs || instr->i_jrel) {
|
||||
instr->i_oparg = instr->i_target->b_offset;
|
||||
else if (instr->i_jrel) {
|
||||
int delta = instr->i_target->b_offset - bsize;
|
||||
instr->i_oparg = delta;
|
||||
if (instr->i_jrel) {
|
||||
instr->i_oparg -= bsize;
|
||||
}
|
||||
if (instrsize(instr->i_oparg) != isize) {
|
||||
extended_arg_recompile = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
continue;
|
||||
if (instr->i_oparg > 0xffff)
|
||||
extended_arg_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4618,7 +4591,7 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c)
|
|||
|
||||
The issue is that in the first loop blocksize() is called
|
||||
which calls instrsize() which requires i_oparg be set
|
||||
appropriately. There is a bootstrap problem because
|
||||
appropriately. There is a bootstrap problem because
|
||||
i_oparg is calculated in the second loop above.
|
||||
|
||||
So we loop until we stop seeing new EXTENDED_ARGs.
|
||||
|
@ -4626,7 +4599,7 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c)
|
|||
ones in jump instructions. So this should converge
|
||||
fairly quickly.
|
||||
*/
|
||||
} while (last_extended_arg_count != extended_arg_count);
|
||||
} while (extended_arg_recompile);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
@ -4772,9 +4745,9 @@ dump_instr(const struct instr *i)
|
|||
char arg[128];
|
||||
|
||||
*arg = '\0';
|
||||
if (i->i_hasarg)
|
||||
if (HAS_ARG(i->i_opcode)) {
|
||||
sprintf(arg, "arg: %d ", i->i_oparg);
|
||||
|
||||
}
|
||||
fprintf(stderr, "line: %d, opcode: %d %s%s%s\n",
|
||||
i->i_lineno, i->i_opcode, arg, jabs, jrel);
|
||||
}
|
||||
|
|
|
@ -14,17 +14,15 @@
|
|||
the appropriate bytes from M___main__.c. */
|
||||
|
||||
static unsigned char M___hello__[] = {
|
||||
99,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,
|
||||
0,64,0,0,0,115,20,0,0,0,100,2,0,90,1,0,
|
||||
101,2,0,100,0,0,131,1,0,1,100,1,0,83,40,3,
|
||||
0,0,0,117,12,0,0,0,72,101,108,108,111,32,119,111,
|
||||
114,108,100,33,78,84,40,3,0,0,0,117,4,0,0,0,
|
||||
84,114,117,101,117,11,0,0,0,105,110,105,116,105,97,108,
|
||||
105,122,101,100,117,5,0,0,0,112,114,105,110,116,40,0,
|
||||
0,0,0,40,0,0,0,0,40,0,0,0,0,117,7,0,
|
||||
0,0,102,108,97,103,46,112,121,117,8,0,0,0,60,109,
|
||||
111,100,117,108,101,62,1,0,0,0,115,2,0,0,0,6,
|
||||
1,
|
||||
227,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,
|
||||
0,64,0,0,0,115,16,0,0,0,100,0,90,0,101,1,
|
||||
100,1,131,1,1,0,100,2,83,0,41,3,84,122,12,72,
|
||||
101,108,108,111,32,119,111,114,108,100,33,78,41,2,218,11,
|
||||
105,110,105,116,105,97,108,105,122,101,100,218,5,112,114,105,
|
||||
110,116,169,0,114,3,0,0,0,114,3,0,0,0,250,22,
|
||||
46,47,84,111,111,108,115,47,102,114,101,101,122,101,47,102,
|
||||
108,97,103,46,112,121,218,8,60,109,111,100,117,108,101,62,
|
||||
1,0,0,0,115,2,0,0,0,4,1,
|
||||
};
|
||||
|
||||
#define SIZE (int)sizeof(M___hello__)
|
||||
|
|
3723
Python/importlib.h
3723
Python/importlib.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -8,8 +8,8 @@
|
|||
#include "code.h"
|
||||
#include "symtable.h"
|
||||
#include "opcode.h"
|
||||
#include "wordcode_helpers.h"
|
||||
|
||||
#define GETARG(arr, i) ((int)((arr[i+2]<<8) + arr[i+1]))
|
||||
#define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==JUMP_FORWARD)
|
||||
#define CONDITIONAL_JUMP(op) (op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \
|
||||
|| op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP)
|
||||
|
@ -17,22 +17,15 @@
|
|||
|| op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \
|
||||
|| op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP)
|
||||
#define JUMPS_ON_TRUE(op) (op==POP_JUMP_IF_TRUE || op==JUMP_IF_TRUE_OR_POP)
|
||||
#define GETJUMPTGT(arr, i) (GETARG(arr,i) + (ABSOLUTE_JUMP(arr[i]) ? 0 : i+3))
|
||||
#define SETARG(arr, i, val) do { \
|
||||
assert(0 <= val && val <= 0xffff); \
|
||||
arr[i+2] = (unsigned char)(((unsigned int)val)>>8); \
|
||||
arr[i+1] = (unsigned char)(((unsigned int)val) & 255); \
|
||||
} while(0)
|
||||
#define CODESIZE(op) (HAS_ARG(op) ? 3 : 1)
|
||||
#define ISBASICBLOCK(blocks, start, bytes) \
|
||||
(blocks[start]==blocks[start+bytes-1])
|
||||
#define GETJUMPTGT(arr, i) (get_arg(arr, i) + (ABSOLUTE_JUMP(arr[i]) ? 0 : i+2))
|
||||
#define ISBASICBLOCK(blocks, start, end) \
|
||||
(blocks[start]==blocks[end])
|
||||
|
||||
|
||||
#define CONST_STACK_CREATE() { \
|
||||
const_stack_size = 256; \
|
||||
const_stack = PyMem_New(PyObject *, const_stack_size); \
|
||||
load_const_stack = PyMem_New(Py_ssize_t, const_stack_size); \
|
||||
if (!const_stack || !load_const_stack) { \
|
||||
if (!const_stack) { \
|
||||
PyErr_NoMemory(); \
|
||||
goto exitError; \
|
||||
} \
|
||||
|
@ -41,27 +34,23 @@
|
|||
#define CONST_STACK_DELETE() do { \
|
||||
if (const_stack) \
|
||||
PyMem_Free(const_stack); \
|
||||
if (load_const_stack) \
|
||||
PyMem_Free(load_const_stack); \
|
||||
} while(0)
|
||||
|
||||
#define CONST_STACK_LEN() (const_stack_top + 1)
|
||||
#define CONST_STACK_LEN() ((unsigned)(const_stack_top + 1))
|
||||
|
||||
#define CONST_STACK_PUSH_OP(i) do { \
|
||||
PyObject *_x; \
|
||||
assert(codestr[i] == LOAD_CONST); \
|
||||
assert(PyList_GET_SIZE(consts) > GETARG(codestr, i)); \
|
||||
_x = PyList_GET_ITEM(consts, GETARG(codestr, i)); \
|
||||
assert(PyList_GET_SIZE(consts) > (Py_ssize_t)get_arg(codestr, i)); \
|
||||
_x = PyList_GET_ITEM(consts, get_arg(codestr, i)); \
|
||||
if (++const_stack_top >= const_stack_size) { \
|
||||
const_stack_size *= 2; \
|
||||
PyMem_Resize(const_stack, PyObject *, const_stack_size); \
|
||||
PyMem_Resize(load_const_stack, Py_ssize_t, const_stack_size); \
|
||||
if (!const_stack || !load_const_stack) { \
|
||||
if (!const_stack) { \
|
||||
PyErr_NoMemory(); \
|
||||
goto exitError; \
|
||||
} \
|
||||
} \
|
||||
load_const_stack[const_stack_top] = i; \
|
||||
const_stack[const_stack_top] = _x; \
|
||||
in_consts = 1; \
|
||||
} while(0)
|
||||
|
@ -70,22 +59,108 @@
|
|||
const_stack_top = -1; \
|
||||
} while(0)
|
||||
|
||||
#define CONST_STACK_TOP() \
|
||||
const_stack[const_stack_top]
|
||||
|
||||
#define CONST_STACK_LASTN(i) \
|
||||
&const_stack[const_stack_top - i + 1]
|
||||
&const_stack[CONST_STACK_LEN() - i]
|
||||
|
||||
#define CONST_STACK_POP(i) do { \
|
||||
assert(const_stack_top + 1 >= i); \
|
||||
assert(CONST_STACK_LEN() >= i); \
|
||||
const_stack_top -= i; \
|
||||
} while(0)
|
||||
|
||||
#define CONST_STACK_OP_LASTN(i) \
|
||||
((const_stack_top >= i - 1) ? load_const_stack[const_stack_top - i + 1] : -1)
|
||||
/* Scans back N consecutive LOAD_CONST instructions, skipping NOPs,
|
||||
returns index of the Nth last's LOAD_CONST's EXTENDED_ARG prefix.
|
||||
Callers are responsible to check CONST_STACK_LEN beforehand.
|
||||
*/
|
||||
static Py_ssize_t
|
||||
lastn_const_start(unsigned char *codestr, Py_ssize_t i, Py_ssize_t n)
|
||||
{
|
||||
assert(n > 0 && (i&1) == 0);
|
||||
for (;;) {
|
||||
i -= 2;
|
||||
assert(i >= 0);
|
||||
if (codestr[i] == LOAD_CONST) {
|
||||
if (!--n) {
|
||||
while (i > 0 && codestr[i-2] == EXTENDED_ARG) {
|
||||
i -= 2;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(codestr[i] == NOP || codestr[i] == EXTENDED_ARG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Scans through EXTENDED ARGs, seeking the index of the effective opcode */
|
||||
static Py_ssize_t
|
||||
find_op(unsigned char *codestr, Py_ssize_t i)
|
||||
{
|
||||
assert((i&1) == 0);
|
||||
while (codestr[i] == EXTENDED_ARG) {
|
||||
i += 2;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Replace LOAD_CONST c1. LOAD_CONST c2 ... LOAD_CONST cn BUILD_TUPLE n
|
||||
/* Given the index of the effective opcode,
|
||||
scan back to construct the oparg with EXTENDED_ARG */
|
||||
static unsigned int
|
||||
get_arg(unsigned char *codestr, Py_ssize_t i)
|
||||
{
|
||||
unsigned int oparg = codestr[i+1];
|
||||
assert((i&1) == 0);
|
||||
if (i >= 2 && codestr[i-2] == EXTENDED_ARG) {
|
||||
oparg |= codestr[i-1] << 8;
|
||||
if (i >= 4 && codestr[i-4] == EXTENDED_ARG) {
|
||||
oparg |= codestr[i-3] << 16;
|
||||
if (i >= 6 && codestr[i-6] == EXTENDED_ARG) {
|
||||
oparg |= codestr[i-5] << 24;
|
||||
}
|
||||
}
|
||||
}
|
||||
return oparg;
|
||||
}
|
||||
|
||||
/* Given the index of the effective opcode,
|
||||
attempt to replace the argument, taking into account EXTENDED_ARG.
|
||||
Returns -1 on failure, or the new op index on success */
|
||||
static Py_ssize_t
|
||||
set_arg(unsigned char *codestr, Py_ssize_t i, unsigned int oparg)
|
||||
{
|
||||
unsigned int curarg = get_arg(codestr, i);
|
||||
int curilen, newilen;
|
||||
if (curarg == oparg)
|
||||
return i;
|
||||
curilen = instrsize(curarg);
|
||||
newilen = instrsize(oparg);
|
||||
if (curilen < newilen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
write_op_arg(codestr + i + 2 - curilen, codestr[i], oparg, newilen);
|
||||
memset(codestr + i + 2 - curilen + newilen, NOP, curilen - newilen);
|
||||
return i-curilen+newilen;
|
||||
}
|
||||
|
||||
/* Attempt to write op/arg at end of specified region of memory.
|
||||
Preceding memory in the region is overwritten with NOPs.
|
||||
Returns -1 on failure, op index on success */
|
||||
static Py_ssize_t
|
||||
copy_op_arg(unsigned char *codestr, Py_ssize_t i, unsigned char op,
|
||||
unsigned int oparg, Py_ssize_t maxi)
|
||||
{
|
||||
int ilen = instrsize(oparg);
|
||||
assert((i&1) == 0);
|
||||
if (i + ilen > maxi) {
|
||||
return -1;
|
||||
}
|
||||
write_op_arg(codestr + maxi - ilen, op, oparg, ilen);
|
||||
memset(codestr + i, NOP, maxi - i - ilen);
|
||||
return maxi - 2;
|
||||
}
|
||||
|
||||
/* Replace LOAD_CONST c1, LOAD_CONST c2 ... LOAD_CONST cn, BUILD_TUPLE n
|
||||
with LOAD_CONST (c1, c2, ... cn).
|
||||
The consts table must still be in list form so that the
|
||||
new constant (c1, c2, ... cn) can be appended.
|
||||
|
@ -94,9 +169,10 @@
|
|||
Also works for BUILD_LIST and BUILT_SET when followed by an "in" or "not in"
|
||||
test; for BUILD_SET it assembles a frozenset rather than a tuple.
|
||||
*/
|
||||
static int
|
||||
tuple_of_constants(unsigned char *codestr, Py_ssize_t n,
|
||||
PyObject *consts, PyObject **objs)
|
||||
static Py_ssize_t
|
||||
fold_tuple_on_constants(unsigned char *codestr, Py_ssize_t c_start,
|
||||
Py_ssize_t opcode_end, unsigned char opcode,
|
||||
PyObject *consts, PyObject **objs, int n)
|
||||
{
|
||||
PyObject *newconst, *constant;
|
||||
Py_ssize_t i, len_consts;
|
||||
|
@ -106,9 +182,9 @@ tuple_of_constants(unsigned char *codestr, Py_ssize_t n,
|
|||
|
||||
/* Buildup new tuple of constants */
|
||||
newconst = PyTuple_New(n);
|
||||
if (newconst == NULL)
|
||||
return 0;
|
||||
len_consts = PyList_GET_SIZE(consts);
|
||||
if (newconst == NULL) {
|
||||
return -1;
|
||||
}
|
||||
for (i=0 ; i<n ; i++) {
|
||||
constant = objs[i];
|
||||
Py_INCREF(constant);
|
||||
|
@ -116,28 +192,26 @@ tuple_of_constants(unsigned char *codestr, Py_ssize_t n,
|
|||
}
|
||||
|
||||
/* If it's a BUILD_SET, use the PyTuple we just built to create a
|
||||
PyFrozenSet, and use that as the constant instead: */
|
||||
if (codestr[0] == BUILD_SET) {
|
||||
Py_XSETREF(newconst, PyFrozenSet_New(newconst));
|
||||
if (newconst == NULL)
|
||||
return 0;
|
||||
PyFrozenSet, and use that as the constant instead: */
|
||||
if (opcode == BUILD_SET) {
|
||||
Py_SETREF(newconst, PyFrozenSet_New(newconst));
|
||||
if (newconst == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Append folded constant onto consts */
|
||||
len_consts = PyList_GET_SIZE(consts);
|
||||
if (PyList_Append(consts, newconst)) {
|
||||
Py_DECREF(newconst);
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(newconst);
|
||||
|
||||
/* Write NOPs over old LOAD_CONSTS and
|
||||
add a new LOAD_CONST newconst on top of the BUILD_TUPLE n */
|
||||
codestr[0] = LOAD_CONST;
|
||||
SETARG(codestr, 0, len_consts);
|
||||
return 1;
|
||||
return copy_op_arg(codestr, c_start, LOAD_CONST, len_consts, opcode_end);
|
||||
}
|
||||
|
||||
/* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP
|
||||
/* Replace LOAD_CONST c1, LOAD_CONST c2, BINOP
|
||||
with LOAD_CONST binop(c1,c2)
|
||||
The consts table must still be in list form so that the
|
||||
new constant can be appended.
|
||||
|
@ -147,20 +221,21 @@ tuple_of_constants(unsigned char *codestr, Py_ssize_t n,
|
|||
is below a threshold value. That keeps pyc files from
|
||||
becoming large in the presence of code like: (None,)*1000.
|
||||
*/
|
||||
static int
|
||||
fold_binops_on_constants(unsigned char *codestr, PyObject *consts, PyObject **objs)
|
||||
static Py_ssize_t
|
||||
fold_binops_on_constants(unsigned char *codestr, Py_ssize_t c_start,
|
||||
Py_ssize_t opcode_end, unsigned char opcode,
|
||||
PyObject *consts, PyObject **objs)
|
||||
{
|
||||
PyObject *newconst, *v, *w;
|
||||
Py_ssize_t len_consts, size;
|
||||
int opcode;
|
||||
|
||||
/* Pre-conditions */
|
||||
assert(PyList_CheckExact(consts));
|
||||
len_consts = PyList_GET_SIZE(consts);
|
||||
|
||||
/* Create new constant */
|
||||
v = objs[0];
|
||||
w = objs[1];
|
||||
opcode = codestr[0];
|
||||
switch (opcode) {
|
||||
case BINARY_POWER:
|
||||
newconst = PyNumber_Power(v, w, Py_None);
|
||||
|
@ -206,50 +281,48 @@ fold_binops_on_constants(unsigned char *codestr, PyObject *consts, PyObject **ob
|
|||
PyErr_Format(PyExc_SystemError,
|
||||
"unexpected binary operation %d on a constant",
|
||||
opcode);
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
if (newconst == NULL) {
|
||||
if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
|
||||
if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
|
||||
PyErr_Clear();
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
size = PyObject_Size(newconst);
|
||||
if (size == -1) {
|
||||
if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
|
||||
return 0;
|
||||
if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
|
||||
return -1;
|
||||
}
|
||||
PyErr_Clear();
|
||||
} else if (size > 20) {
|
||||
Py_DECREF(newconst);
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Append folded constant into consts table */
|
||||
len_consts = PyList_GET_SIZE(consts);
|
||||
if (PyList_Append(consts, newconst)) {
|
||||
Py_DECREF(newconst);
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(newconst);
|
||||
|
||||
/* Write NOP NOP NOP NOP LOAD_CONST newconst */
|
||||
codestr[-2] = LOAD_CONST;
|
||||
SETARG(codestr, -2, len_consts);
|
||||
return 1;
|
||||
return copy_op_arg(codestr, c_start, LOAD_CONST, len_consts, opcode_end);
|
||||
}
|
||||
|
||||
static int
|
||||
fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts, PyObject *v)
|
||||
static Py_ssize_t
|
||||
fold_unaryops_on_constants(unsigned char *codestr, Py_ssize_t c_start,
|
||||
Py_ssize_t opcode_end, unsigned char opcode,
|
||||
PyObject *consts, PyObject *v)
|
||||
{
|
||||
PyObject *newconst;
|
||||
Py_ssize_t len_consts;
|
||||
int opcode;
|
||||
|
||||
/* Pre-conditions */
|
||||
assert(PyList_CheckExact(consts));
|
||||
assert(codestr[0] == LOAD_CONST);
|
||||
len_consts = PyList_GET_SIZE(consts);
|
||||
|
||||
/* Create new constant */
|
||||
opcode = codestr[3];
|
||||
switch (opcode) {
|
||||
case UNARY_NEGATIVE:
|
||||
newconst = PyNumber_Negative(v);
|
||||
|
@ -265,35 +338,31 @@ fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts, PyObject *v
|
|||
PyErr_Format(PyExc_SystemError,
|
||||
"unexpected unary operation %d on a constant",
|
||||
opcode);
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
if (newconst == NULL) {
|
||||
if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
|
||||
if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
|
||||
PyErr_Clear();
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Append folded constant into consts table */
|
||||
len_consts = PyList_GET_SIZE(consts);
|
||||
if (PyList_Append(consts, newconst)) {
|
||||
Py_DECREF(newconst);
|
||||
PyErr_Clear();
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(newconst);
|
||||
|
||||
/* Write NOP LOAD_CONST newconst */
|
||||
codestr[0] = NOP;
|
||||
codestr[1] = LOAD_CONST;
|
||||
SETARG(codestr, 1, len_consts);
|
||||
return 1;
|
||||
return copy_op_arg(codestr, c_start, LOAD_CONST, len_consts, opcode_end);
|
||||
}
|
||||
|
||||
static unsigned int *
|
||||
markblocks(unsigned char *code, Py_ssize_t len)
|
||||
{
|
||||
unsigned int *blocks = PyMem_New(unsigned int, len);
|
||||
int i,j, opcode, blockcnt = 0;
|
||||
int i, j, opcode, blockcnt = 0;
|
||||
|
||||
if (blocks == NULL) {
|
||||
PyErr_NoMemory();
|
||||
|
@ -302,7 +371,7 @@ markblocks(unsigned char *code, Py_ssize_t len)
|
|||
memset(blocks, 0, len*sizeof(int));
|
||||
|
||||
/* Mark labels in the first pass */
|
||||
for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
|
||||
for (i=0 ; i<len ; i+=2) {
|
||||
opcode = code[i];
|
||||
switch (opcode) {
|
||||
case FOR_ITER:
|
||||
|
@ -324,7 +393,7 @@ markblocks(unsigned char *code, Py_ssize_t len)
|
|||
}
|
||||
}
|
||||
/* Build block numbers in the second pass */
|
||||
for (i=0 ; i<len ; i++) {
|
||||
for (i=0 ; i<len ; i+=2) {
|
||||
blockcnt += blocks[i]; /* increment blockcnt over labels */
|
||||
blocks[i] = blockcnt;
|
||||
}
|
||||
|
@ -335,33 +404,27 @@ markblocks(unsigned char *code, Py_ssize_t len)
|
|||
The consts object should still be in list form to allow new constants
|
||||
to be appended.
|
||||
|
||||
To keep the optimizer simple, it bails out (does nothing) for code that
|
||||
has a length over 32,700, and does not calculate extended arguments.
|
||||
That allows us to avoid overflow and sign issues. Likewise, it bails when
|
||||
the lineno table has complex encoding for gaps >= 255. EXTENDED_ARG can
|
||||
appear before MAKE_FUNCTION; in this case both opcodes are skipped.
|
||||
EXTENDED_ARG preceding any other opcode causes the optimizer to bail.
|
||||
To keep the optimizer simple, it bails when the lineno table has complex
|
||||
encoding for gaps >= 255.
|
||||
|
||||
Optimizations are restricted to simple transformations occuring within a
|
||||
single basic block. All transformations keep the code size the same or
|
||||
smaller. For those that reduce size, the gaps are initially filled with
|
||||
NOPs. Later those NOPs are removed and the jump addresses retargeted in
|
||||
a single pass. Code offset is adjusted accordingly. */
|
||||
a single pass. */
|
||||
|
||||
PyObject *
|
||||
PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
||||
PyObject *lnotab_obj)
|
||||
{
|
||||
Py_ssize_t i, j, codelen;
|
||||
int nops, h, adj;
|
||||
int tgt, tgttgt, opcode;
|
||||
Py_ssize_t h, i, nexti, op_start, codelen, tgt;
|
||||
unsigned int j, nops;
|
||||
unsigned char opcode, nextop;
|
||||
unsigned char *codestr = NULL;
|
||||
unsigned char *lnotab;
|
||||
int *addrmap = NULL;
|
||||
int cum_orig_offset, last_offset;
|
||||
unsigned int cum_orig_offset, last_offset;
|
||||
Py_ssize_t tabsiz;
|
||||
PyObject **const_stack = NULL;
|
||||
Py_ssize_t *load_const_stack = NULL;
|
||||
Py_ssize_t const_stack_top = -1;
|
||||
Py_ssize_t const_stack_size = 0;
|
||||
int in_consts = 0; /* whether we are in a LOAD_CONST sequence */
|
||||
|
@ -383,11 +446,9 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
|||
/* Note: -128 and 127 special values for line number delta are ok,
|
||||
the peephole optimizer doesn't modify line numbers. */
|
||||
|
||||
/* Avoid situations where jump retargeting could overflow */
|
||||
assert(PyBytes_Check(code));
|
||||
codelen = PyBytes_GET_SIZE(code);
|
||||
if (codelen > 32700)
|
||||
goto exitUnchanged;
|
||||
assert(codelen % 2 == 0);
|
||||
|
||||
/* Make a modifiable copy of the code string */
|
||||
codestr = (unsigned char *)PyMem_Malloc(codelen);
|
||||
|
@ -398,21 +459,6 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
|||
codestr = (unsigned char *)memcpy(codestr,
|
||||
PyBytes_AS_STRING(code), codelen);
|
||||
|
||||
/* Verify that RETURN_VALUE terminates the codestring. This allows
|
||||
the various transformation patterns to look ahead several
|
||||
instructions without additional checks to make sure they are not
|
||||
looking beyond the end of the code string.
|
||||
*/
|
||||
if (codestr[codelen-1] != RETURN_VALUE)
|
||||
goto exitUnchanged;
|
||||
|
||||
/* Mapping to new jump targets after NOPs are removed */
|
||||
addrmap = PyMem_New(int, codelen);
|
||||
if (addrmap == NULL) {
|
||||
PyErr_NoMemory();
|
||||
goto exitError;
|
||||
}
|
||||
|
||||
blocks = markblocks(codestr, codelen);
|
||||
if (blocks == NULL)
|
||||
goto exitError;
|
||||
|
@ -420,9 +466,17 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
|||
|
||||
CONST_STACK_CREATE();
|
||||
|
||||
for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
|
||||
reoptimize_current:
|
||||
for (i=find_op(codestr, 0) ; i<codelen ; i=nexti) {
|
||||
opcode = codestr[i];
|
||||
op_start = i;
|
||||
while (op_start >= 2 && codestr[op_start-2] == EXTENDED_ARG) {
|
||||
op_start -= 2;
|
||||
}
|
||||
|
||||
nexti = i + 2;
|
||||
while (nexti < codelen && codestr[nexti] == EXTENDED_ARG)
|
||||
nexti += 2;
|
||||
nextop = nexti < codelen ? codestr[nexti] : 0;
|
||||
|
||||
if (!in_consts) {
|
||||
CONST_STACK_RESET();
|
||||
|
@ -433,14 +487,12 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
|||
/* Replace UNARY_NOT POP_JUMP_IF_FALSE
|
||||
with POP_JUMP_IF_TRUE */
|
||||
case UNARY_NOT:
|
||||
if (codestr[i+1] != POP_JUMP_IF_FALSE
|
||||
|| !ISBASICBLOCK(blocks,i,4))
|
||||
continue;
|
||||
j = GETARG(codestr, i+1);
|
||||
codestr[i] = POP_JUMP_IF_TRUE;
|
||||
SETARG(codestr, i, j);
|
||||
codestr[i+3] = NOP;
|
||||
goto reoptimize_current;
|
||||
if (nextop != POP_JUMP_IF_FALSE
|
||||
|| !ISBASICBLOCK(blocks, op_start, i+2))
|
||||
break;
|
||||
memset(codestr + op_start, NOP, i - op_start + 2);
|
||||
codestr[nexti] = POP_JUMP_IF_TRUE;
|
||||
break;
|
||||
|
||||
/* not a is b --> a is not b
|
||||
not a in b --> a not in b
|
||||
|
@ -448,78 +500,79 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
|||
not a not in b --> a in b
|
||||
*/
|
||||
case COMPARE_OP:
|
||||
j = GETARG(codestr, i);
|
||||
if (j < 6 || j > 9 ||
|
||||
codestr[i+3] != UNARY_NOT ||
|
||||
!ISBASICBLOCK(blocks,i,4))
|
||||
continue;
|
||||
SETARG(codestr, i, (j^1));
|
||||
codestr[i+3] = NOP;
|
||||
j = get_arg(codestr, i);
|
||||
if (j < 6 || j > 9 ||
|
||||
nextop != UNARY_NOT ||
|
||||
!ISBASICBLOCK(blocks, op_start, i + 2))
|
||||
break;
|
||||
codestr[i+1] = (j^1);
|
||||
memset(codestr + i + 2, NOP, nexti - i);
|
||||
break;
|
||||
|
||||
/* Skip over LOAD_CONST trueconst
|
||||
POP_JUMP_IF_FALSE xx. This improves
|
||||
"while 1" performance. */
|
||||
POP_JUMP_IF_FALSE xx. This improves
|
||||
"while 1" performance. */
|
||||
case LOAD_CONST:
|
||||
CONST_STACK_PUSH_OP(i);
|
||||
j = GETARG(codestr, i);
|
||||
if (codestr[i+3] != POP_JUMP_IF_FALSE ||
|
||||
!ISBASICBLOCK(blocks,i,6) ||
|
||||
!PyObject_IsTrue(PyList_GET_ITEM(consts, j)))
|
||||
continue;
|
||||
memset(codestr+i, NOP, 6);
|
||||
CONST_STACK_RESET();
|
||||
if (nextop != POP_JUMP_IF_FALSE ||
|
||||
!ISBASICBLOCK(blocks, op_start, i + 2) ||
|
||||
!PyObject_IsTrue(PyList_GET_ITEM(consts, get_arg(codestr, i))))
|
||||
break;
|
||||
memset(codestr + op_start, NOP, nexti - op_start + 2);
|
||||
CONST_STACK_POP(1);
|
||||
break;
|
||||
|
||||
/* Try to fold tuples of constants (includes a case for lists and sets
|
||||
which are only used for "in" and "not in" tests).
|
||||
/* Try to fold tuples of constants (includes a case for lists
|
||||
and sets which are only used for "in" and "not in" tests).
|
||||
Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
|
||||
Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
|
||||
Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
|
||||
case BUILD_TUPLE:
|
||||
case BUILD_LIST:
|
||||
case BUILD_SET:
|
||||
j = GETARG(codestr, i);
|
||||
if (j == 0)
|
||||
break;
|
||||
h = CONST_STACK_OP_LASTN(j);
|
||||
assert((h >= 0 || CONST_STACK_LEN() < j));
|
||||
if (h >= 0 && j > 0 && j <= CONST_STACK_LEN() &&
|
||||
((opcode == BUILD_TUPLE &&
|
||||
ISBASICBLOCK(blocks, h, i-h+3)) ||
|
||||
((opcode == BUILD_LIST || opcode == BUILD_SET) &&
|
||||
codestr[i+3]==COMPARE_OP &&
|
||||
ISBASICBLOCK(blocks, h, i-h+6) &&
|
||||
(GETARG(codestr,i+3)==6 ||
|
||||
GETARG(codestr,i+3)==7))) &&
|
||||
tuple_of_constants(&codestr[i], j, consts, CONST_STACK_LASTN(j))) {
|
||||
assert(codestr[i] == LOAD_CONST);
|
||||
memset(&codestr[h], NOP, i - h);
|
||||
CONST_STACK_POP(j);
|
||||
CONST_STACK_PUSH_OP(i);
|
||||
break;
|
||||
j = get_arg(codestr, i);
|
||||
if (j > 0 && CONST_STACK_LEN() >= j) {
|
||||
h = lastn_const_start(codestr, op_start, j);
|
||||
if ((opcode == BUILD_TUPLE &&
|
||||
ISBASICBLOCK(blocks, h, op_start)) ||
|
||||
((opcode == BUILD_LIST || opcode == BUILD_SET) &&
|
||||
((nextop==COMPARE_OP &&
|
||||
(codestr[nexti+1]==6 ||
|
||||
codestr[nexti+1]==7)) ||
|
||||
nextop == GET_ITER) && ISBASICBLOCK(blocks, h, i + 2))) {
|
||||
h = fold_tuple_on_constants(codestr, h, i+2, opcode,
|
||||
consts, CONST_STACK_LASTN(j), j);
|
||||
if (h >= 0) {
|
||||
CONST_STACK_POP(j);
|
||||
CONST_STACK_PUSH_OP(h);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (codestr[i+3] != UNPACK_SEQUENCE ||
|
||||
!ISBASICBLOCK(blocks,i,6) ||
|
||||
j != GETARG(codestr, i+3) ||
|
||||
if (nextop != UNPACK_SEQUENCE ||
|
||||
!ISBASICBLOCK(blocks, op_start, i + 2) ||
|
||||
j != get_arg(codestr, nexti) ||
|
||||
opcode == BUILD_SET)
|
||||
continue;
|
||||
if (j == 1) {
|
||||
memset(codestr+i, NOP, 6);
|
||||
break;
|
||||
if (j < 2) {
|
||||
memset(codestr+op_start, NOP, nexti - op_start + 2);
|
||||
} else if (j == 2) {
|
||||
codestr[i] = ROT_TWO;
|
||||
memset(codestr+i+1, NOP, 5);
|
||||
codestr[op_start] = ROT_TWO;
|
||||
codestr[op_start + 1] = 0;
|
||||
memset(codestr + op_start + 2, NOP, nexti - op_start);
|
||||
CONST_STACK_RESET();
|
||||
} else if (j == 3) {
|
||||
codestr[i] = ROT_THREE;
|
||||
codestr[i+1] = ROT_TWO;
|
||||
memset(codestr+i+2, NOP, 4);
|
||||
codestr[op_start] = ROT_THREE;
|
||||
codestr[op_start + 1] = 0;
|
||||
codestr[op_start + 2] = ROT_TWO;
|
||||
codestr[op_start + 3] = 0;
|
||||
memset(codestr + op_start + 4, NOP, nexti - op_start - 2);
|
||||
CONST_STACK_RESET();
|
||||
}
|
||||
break;
|
||||
|
||||
/* Fold binary ops on constants.
|
||||
LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
|
||||
LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
|
||||
case BINARY_POWER:
|
||||
case BINARY_MULTIPLY:
|
||||
case BINARY_TRUE_DIVIDE:
|
||||
|
@ -533,35 +586,34 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
|||
case BINARY_AND:
|
||||
case BINARY_XOR:
|
||||
case BINARY_OR:
|
||||
/* NOTE: LOAD_CONST is saved at `i-2` since it has an arg
|
||||
while BINOP hasn't */
|
||||
h = CONST_STACK_OP_LASTN(2);
|
||||
assert((h >= 0 || CONST_STACK_LEN() < 2));
|
||||
if (h >= 0 &&
|
||||
ISBASICBLOCK(blocks, h, i-h+1) &&
|
||||
fold_binops_on_constants(&codestr[i], consts, CONST_STACK_LASTN(2))) {
|
||||
i -= 2;
|
||||
memset(&codestr[h], NOP, i - h);
|
||||
assert(codestr[i] == LOAD_CONST);
|
||||
CONST_STACK_POP(2);
|
||||
CONST_STACK_PUSH_OP(i);
|
||||
if (CONST_STACK_LEN() < 2)
|
||||
break;
|
||||
h = lastn_const_start(codestr, op_start, 2);
|
||||
if (ISBASICBLOCK(blocks, h, op_start)) {
|
||||
h = fold_binops_on_constants(codestr, h, i+2, opcode,
|
||||
consts, CONST_STACK_LASTN(2));
|
||||
if (h >= 0) {
|
||||
CONST_STACK_POP(2);
|
||||
CONST_STACK_PUSH_OP(h);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Fold unary ops on constants.
|
||||
LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
|
||||
LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
|
||||
case UNARY_NEGATIVE:
|
||||
case UNARY_INVERT:
|
||||
case UNARY_POSITIVE:
|
||||
h = CONST_STACK_OP_LASTN(1);
|
||||
assert((h >= 0 || CONST_STACK_LEN() < 1));
|
||||
if (h >= 0 &&
|
||||
ISBASICBLOCK(blocks, h, i-h+1) &&
|
||||
fold_unaryops_on_constants(&codestr[i-3], consts, CONST_STACK_TOP())) {
|
||||
i -= 2;
|
||||
assert(codestr[i] == LOAD_CONST);
|
||||
CONST_STACK_POP(1);
|
||||
CONST_STACK_PUSH_OP(i);
|
||||
if (CONST_STACK_LEN() < 1)
|
||||
break;
|
||||
h = lastn_const_start(codestr, op_start, 1);
|
||||
if (ISBASICBLOCK(blocks, h, op_start)) {
|
||||
h = fold_unaryops_on_constants(codestr, h, i+2, opcode,
|
||||
consts, *CONST_STACK_LASTN(1));
|
||||
if (h >= 0) {
|
||||
CONST_STACK_POP(1);
|
||||
CONST_STACK_PUSH_OP(h);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -576,25 +628,24 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
|||
x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
|
||||
--> x:JUMP_IF_FALSE_OR_POP z
|
||||
x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
|
||||
--> x:POP_JUMP_IF_FALSE y+3
|
||||
where y+3 is the instruction following the second test.
|
||||
--> x:POP_JUMP_IF_FALSE y+2
|
||||
where y+2 is the instruction following the second test.
|
||||
*/
|
||||
case JUMP_IF_FALSE_OR_POP:
|
||||
case JUMP_IF_TRUE_OR_POP:
|
||||
tgt = GETJUMPTGT(codestr, i);
|
||||
h = get_arg(codestr, i);
|
||||
tgt = find_op(codestr, h);
|
||||
|
||||
j = codestr[tgt];
|
||||
if (CONDITIONAL_JUMP(j)) {
|
||||
/* NOTE: all possible jumps here are
|
||||
absolute! */
|
||||
if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
|
||||
/* The second jump will be
|
||||
taken iff the first is. */
|
||||
tgttgt = GETJUMPTGT(codestr, tgt);
|
||||
/* The current opcode inherits
|
||||
its target's stack behaviour */
|
||||
codestr[i] = j;
|
||||
SETARG(codestr, i, tgttgt);
|
||||
goto reoptimize_current;
|
||||
taken iff the first is.
|
||||
The current opcode inherits
|
||||
its target's stack effect */
|
||||
h = set_arg(codestr, i, get_arg(codestr, tgt));
|
||||
} else {
|
||||
/* The second jump is not taken
|
||||
if the first is (so jump past
|
||||
|
@ -603,12 +654,15 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
|||
they're not taken (so change
|
||||
the first jump to pop its
|
||||
argument when it's taken). */
|
||||
if (JUMPS_ON_TRUE(opcode))
|
||||
codestr[i] = POP_JUMP_IF_TRUE;
|
||||
else
|
||||
codestr[i] = POP_JUMP_IF_FALSE;
|
||||
SETARG(codestr, i, (tgt + 3));
|
||||
goto reoptimize_current;
|
||||
h = set_arg(codestr, i, tgt + 2);
|
||||
j = opcode == JUMP_IF_TRUE_OR_POP ?
|
||||
POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE;
|
||||
}
|
||||
|
||||
if (h >= 0) {
|
||||
nexti = h;
|
||||
codestr[nexti] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Intentional fallthrough */
|
||||
|
@ -625,76 +679,73 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
|||
case SETUP_FINALLY:
|
||||
case SETUP_WITH:
|
||||
case SETUP_ASYNC_WITH:
|
||||
tgt = GETJUMPTGT(codestr, i);
|
||||
h = GETJUMPTGT(codestr, i);
|
||||
tgt = find_op(codestr, h);
|
||||
/* Replace JUMP_* to a RETURN into just a RETURN */
|
||||
if (UNCONDITIONAL_JUMP(opcode) &&
|
||||
codestr[tgt] == RETURN_VALUE) {
|
||||
codestr[i] = RETURN_VALUE;
|
||||
memset(codestr+i+1, NOP, 2);
|
||||
continue;
|
||||
codestr[op_start] = RETURN_VALUE;
|
||||
codestr[op_start + 1] = 0;
|
||||
memset(codestr + op_start + 2, NOP, i - op_start);
|
||||
} else if (UNCONDITIONAL_JUMP(codestr[tgt])) {
|
||||
j = GETJUMPTGT(codestr, tgt);
|
||||
if (opcode == JUMP_FORWARD) { /* JMP_ABS can go backwards */
|
||||
opcode = JUMP_ABSOLUTE;
|
||||
} else if (!ABSOLUTE_JUMP(opcode)) {
|
||||
if ((Py_ssize_t)j < i + 2) {
|
||||
break; /* No backward relative jumps */
|
||||
}
|
||||
j -= i + 2; /* Calc relative jump addr */
|
||||
}
|
||||
copy_op_arg(codestr, op_start, opcode, j, i+2);
|
||||
}
|
||||
if (!UNCONDITIONAL_JUMP(codestr[tgt]))
|
||||
continue;
|
||||
tgttgt = GETJUMPTGT(codestr, tgt);
|
||||
if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */
|
||||
opcode = JUMP_ABSOLUTE;
|
||||
if (!ABSOLUTE_JUMP(opcode))
|
||||
tgttgt -= i + 3; /* Calc relative jump addr */
|
||||
if (tgttgt < 0) /* No backward relative jumps */
|
||||
continue;
|
||||
codestr[i] = opcode;
|
||||
SETARG(codestr, i, tgttgt);
|
||||
break;
|
||||
|
||||
case EXTENDED_ARG:
|
||||
if (codestr[i+3] != MAKE_FUNCTION)
|
||||
goto exitUnchanged;
|
||||
/* don't visit MAKE_FUNCTION as GETARG will be wrong */
|
||||
i += 3;
|
||||
break;
|
||||
|
||||
/* Replace RETURN LOAD_CONST None RETURN with just RETURN */
|
||||
/* Remove unreachable JUMPs after RETURN */
|
||||
/* Remove unreachable ops after RETURN */
|
||||
case RETURN_VALUE:
|
||||
if (i+4 >= codelen)
|
||||
continue;
|
||||
if (codestr[i+4] == RETURN_VALUE &&
|
||||
ISBASICBLOCK(blocks,i,5))
|
||||
memset(codestr+i+1, NOP, 4);
|
||||
else if (UNCONDITIONAL_JUMP(codestr[i+1]) &&
|
||||
ISBASICBLOCK(blocks,i,4))
|
||||
memset(codestr+i+1, NOP, 3);
|
||||
h = i + 2;
|
||||
while (h + 2 < codelen && ISBASICBLOCK(blocks, i, h + 2)) {
|
||||
h += 2;
|
||||
}
|
||||
if (h > i + 2) {
|
||||
memset(codestr + i + 2, NOP, h - i);
|
||||
nexti = find_op(codestr, h);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fixup lnotab */
|
||||
for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
|
||||
for (i=0, nops=0 ; i<codelen ; i += 2) {
|
||||
assert(i - nops <= INT_MAX);
|
||||
/* original code offset => new code offset */
|
||||
addrmap[i] = (int)(i - nops);
|
||||
blocks[i] = i - nops;
|
||||
if (codestr[i] == NOP)
|
||||
nops++;
|
||||
nops += 2;
|
||||
}
|
||||
cum_orig_offset = 0;
|
||||
last_offset = 0;
|
||||
for (i=0 ; i < tabsiz ; i+=2) {
|
||||
int offset_delta, new_offset;
|
||||
unsigned int offset_delta, new_offset;
|
||||
cum_orig_offset += lnotab[i];
|
||||
new_offset = addrmap[cum_orig_offset];
|
||||
assert((cum_orig_offset & 1) == 0);
|
||||
new_offset = blocks[cum_orig_offset];
|
||||
offset_delta = new_offset - last_offset;
|
||||
assert(0 <= offset_delta && offset_delta <= 255);
|
||||
assert(offset_delta <= 255);
|
||||
lnotab[i] = (unsigned char)offset_delta;
|
||||
last_offset = new_offset;
|
||||
}
|
||||
|
||||
/* Remove NOPs and fixup jump targets */
|
||||
for (i=0, h=0 ; i<codelen ; ) {
|
||||
for (op_start=0, i=0, h=0 ; i<codelen ; i+=2, op_start=i) {
|
||||
j = codestr[i+1];
|
||||
while (codestr[i] == EXTENDED_ARG) {
|
||||
i += 2;
|
||||
j = j<<8 | codestr[i+1];
|
||||
}
|
||||
opcode = codestr[i];
|
||||
switch (opcode) {
|
||||
case NOP:
|
||||
i++;
|
||||
continue;
|
||||
case NOP:continue;
|
||||
|
||||
case JUMP_ABSOLUTE:
|
||||
case CONTINUE_LOOP:
|
||||
|
@ -702,8 +753,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
|||
case POP_JUMP_IF_TRUE:
|
||||
case JUMP_IF_FALSE_OR_POP:
|
||||
case JUMP_IF_TRUE_OR_POP:
|
||||
j = addrmap[GETARG(codestr, i)];
|
||||
SETARG(codestr, i, j);
|
||||
j = blocks[j];
|
||||
break;
|
||||
|
||||
case FOR_ITER:
|
||||
|
@ -713,31 +763,31 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
|||
case SETUP_FINALLY:
|
||||
case SETUP_WITH:
|
||||
case SETUP_ASYNC_WITH:
|
||||
j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
|
||||
SETARG(codestr, i, j);
|
||||
j = blocks[j + i + 2] - blocks[i] - 2;
|
||||
break;
|
||||
}
|
||||
adj = CODESIZE(opcode);
|
||||
while (adj--)
|
||||
codestr[h++] = codestr[i++];
|
||||
nexti = i - op_start + 2;
|
||||
if (instrsize(j) > nexti)
|
||||
goto exitUnchanged;
|
||||
/* If instrsize(j) < nexti, we'll emit EXTENDED_ARG 0 */
|
||||
write_op_arg(codestr + h, opcode, j, nexti);
|
||||
h += nexti;
|
||||
}
|
||||
assert(h + nops == codelen);
|
||||
assert(h + (Py_ssize_t)nops == codelen);
|
||||
|
||||
code = PyBytes_FromStringAndSize((char *)codestr, h);
|
||||
CONST_STACK_DELETE();
|
||||
PyMem_Free(addrmap);
|
||||
PyMem_Free(codestr);
|
||||
PyMem_Free(blocks);
|
||||
code = PyBytes_FromStringAndSize((char *)codestr, h);
|
||||
PyMem_Free(codestr);
|
||||
return code;
|
||||
|
||||
exitError:
|
||||
code = NULL;
|
||||
|
||||
exitUnchanged:
|
||||
Py_XINCREF(code);
|
||||
CONST_STACK_DELETE();
|
||||
PyMem_Free(blocks);
|
||||
PyMem_Free(addrmap);
|
||||
PyMem_Free(codestr);
|
||||
Py_XINCREF(code);
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/* This file contains code shared by the compiler and the peephole
|
||||
optimizer.
|
||||
*/
|
||||
|
||||
/* Minimum number of bytes necessary to encode instruction with EXTENDED_ARGs */
|
||||
static int
|
||||
instrsize(unsigned int oparg)
|
||||
{
|
||||
return oparg <= 0xff ? 2 :
|
||||
oparg <= 0xffff ? 4 :
|
||||
oparg <= 0xffffff ? 6 :
|
||||
8;
|
||||
}
|
||||
|
||||
/* Spits out op/oparg pair using ilen bytes. codestr should be pointed at the
|
||||
desired location of the first EXTENDED_ARG */
|
||||
static void
|
||||
write_op_arg(unsigned char *codestr, unsigned char opcode,
|
||||
unsigned int oparg, int ilen)
|
||||
{
|
||||
switch (ilen) {
|
||||
case 8:
|
||||
*codestr++ = EXTENDED_ARG;
|
||||
*codestr++ = (oparg >> 24) & 0xff;
|
||||
case 6:
|
||||
*codestr++ = EXTENDED_ARG;
|
||||
*codestr++ = (oparg >> 16) & 0xff;
|
||||
case 4:
|
||||
*codestr++ = EXTENDED_ARG;
|
||||
*codestr++ = (oparg >> 8) & 0xff;
|
||||
case 2:
|
||||
*codestr++ = opcode;
|
||||
*codestr++ = oparg & 0xff;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue