8000 gh-90997: bpo-46841: Disassembly of quickened code by penguin-wwy · Pull Request #32099 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-90997: bpo-46841: Disassembly of quickened code #32099

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Apr 19, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Reset deoptmap and fix test_dis
  • Loading branch information
penguin-wwy committed Mar 24, 2022
commit ceabedbe42823becee2326be86fe56fc151865f4
34 changes: 20 additions & 14 deletions Lib/dis.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
8000
CACHE = opmap["CACHE"]

def deoptop(op):
name = opname[op]
return opmap[deoptmap[name]] if name in deoptmap else opmap[name]

def _try_compile(source, name):
"""Attempts to compile the given source, first as an expression and
then as a statement if the first approach fails.
Expand Down Expand Up @@ -428,40 +432,43 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
# 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.
deop = deoptop(op)
argval = arg
if op in hasconst:
argval, argrepr = _get_const_info(op, arg, co_consts)
elif op in hasname:
if op == LOAD_GLOBAL:
if deop in hasconst:
argval, argrepr = _get_const_info(deop, arg, co_consts)
elif deop in hasname:
if deop == LOAD_GLOBAL:
argval, argrepr = _get_name_info(arg//2, get_name)
if (arg & 1) and argrepr:
argrepr = "NULL + " + argrepr
else:
argval, argrepr = _get_name_info(arg, get_name)
elif op in hasjabs:
elif deop in hasjabs:
argval = arg*2
argrepr = "to " + repr(argval)
elif op in hasjrel:
elif deop in hasjrel:
argval = offset + 2 + arg*2
argrepr = "to " + repr(argval)
elif op in haslocal or op in hasfree:
elif deop in haslocal or deop in hasfree:
argval, argrepr = _get_name_info(arg, varname_from_oparg)
elif op in hascompare:
elif deop in hascompare:
argval = cmp_op[arg]
argrepr = argval
elif op == FORMAT_VALUE:
elif deop == FORMAT_VALUE:
argval, argrepr = FORMAT_VALUE_CONVERTERS[arg & 0x3]
argval = (argval, bool(arg & 0x4))
if argval[1]:
if argrepr:
argrepr += ', '
argrepr += 'with format'
elif op == MAKE_FUNCTION:
elif deop == MAKE_FUNCTION:
argrepr = ', '.join(s for i, s in enumerate(MAKE_FUNCTION_FLAGS)
if arg & (1<<i))
elif op == BINARY_OP:
elif deop == BINARY_OP:
_, argrepr = _nb_ops[arg]
name = opname[deoptmap[op]] if not quickened and op in deoptmap else opname[op]
name = opname[op]
if not quickened and name in deoptmap:
name = deoptmap[name]
yield Instruction(name, op,
arg, argval, argrepr,
offset, starts_line, is_jump_target, positions)
Expand Down Expand Up @@ -546,8 +553,7 @@ def _unpack_opargs(code):
extended_arg = 0
for i in range(0, len(code), 2):
op = code[i]
oop = op if op not in deoptmap else deoptmap[op]
if oop >= HAVE_ARGUMENT:
if deoptop(op) >= HAVE_ARGUMENT:
arg = code[i+1] | extended_arg
extended_arg = (arg << 8) if op == EXTENDED_ARG else 0
# The oparg is stored as a signed integer
Expand Down
18 changes: 9 additions & 9 deletions Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,13 @@

opmap = {}
opname = ['<%r>' % (op,) for op in range(256)]
deoptmap = {}

_inline_cache_entries = [0] * 256
_empty_slot = [i for i in range(256)]

def def_op(name, op, entries=0):
opname[op] = name
opmap[name] = op
_inline_cache_entries[op] = entries
_empty_slot[op] = False

def name_op(name, op, entries=0):
def_op(name, op, entries)
Expand Down Expand Up @@ -344,12 +341,15 @@ def spec_op(origin_name, spec_name, counter):
opcode for family in _specializations.values() for opcode in family
]

_empty_slot = [i for i in filter(lambda e: e is not False, _empty_slot)]
_specialized_counter = 0
for basic, family in _specializations.items():
for specialized in family:
spec_op(basic, specialized, _specialized_counter)
_specialized_counter += 1
_empty_slot = [slot for slot, name in enumerate(opname) if name.startswith("<")]
for spec_op, specialized in zip(_empty_slot, _specialized_instructions):
# fill opname and opmap
opname[spec_op] = specialized
opmap[specialized] = spec_op

deoptmap = {
specialized: base for base, family in _specializations.items() for specialized in family
}

_specialization_stats = [
"success",
Expand Down
4 changes: 1 addition & 3 deletions Lib/test/test_dis.py
Original file line number Diff line number Diff line change
Expand Up @@ -682,9 +682,7 @@ def test_boundaries(self):

def test_widths(self):
for opcode, opname in enumerate(dis.opname):
if opname in ('BUILD_MAP_UNPACK_WITH_CALL',
'BUILD_TUPLE_UNPACK_WITH_CALL',
'JUMP_IF_NOT_EXC_MATCH'):
if opname in dis.deoptmap or opname == "JUMP_IF_NOT_EXC_MATCH":
continue
with self.subTest(opname=opname):
width = dis._OPNAME_WIDTH
Expand Down
8 changes: 4 additions & 4 deletions Tools/scripts/generate_opcode_h.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ def main(opcode_py, outfile='Include/opcode.h'):
with open(outfile, 'w') as fobj:
fobj.write(header)
for name in opname:
if name in opmap and opmap[name] not in deoptmap:
if name in opmap and name not in deoptmap:
fobj.write(DEFINE.format(name, opmap[name]))
if name == 'POP_EXCEPT': # Special entry for HAVE_ARGUMENT
fobj.write(DEFINE.format("HAVE_ARGUMENT", opcode["HAVE_ARGUMENT"]))

for spec_op in deoptmap:
fobj.write(DEFINE.format(opname[spec_op], spec_op))
for spec_name in deoptmap:
fobj.write(DEFINE.format(spec_name, opmap[spec_name]))
fobj.write(DEFINE.format('DO_TRACING', 255))
fobj.write("\nextern const uint8_t _PyOpcode_Caches[256];\n")
fobj.write("\nextern const uint8_t _PyOpcode_Deopt[256];\n")
Expand All @@ -82,7 +82,7 @@ def main(opcode_py, outfile='Include/opcode.h'):
fobj.write("};\n")
fobj.write("\nconst uint8_t _PyOpcode_Deopt[256] = {\n")
for opt, deopt in sorted(deoptmap.items()):
fobj.write(f" [{opname[opt]}] = {opname[deopt]},\n")
fobj.write(f" [{opt}] = {deopt},\n")
fobj.write("};\n")
fobj.write("#endif /* OPCODE_TABLES */\n")

Expand Down
0