@@ -267,9 +267,10 @@ def show_code(co, *, file=None):
267267 'starts_line' ,
268268 'line_number' ,
269269 'label' ,
270- 'positions'
270+ 'positions' ,
271+ 'cache_info' ,
271272 ],
272- defaults = [None , None ]
273+ defaults = [None , None , None ]
273274)
274275
275276_Instruction .opname .__doc__ = "Human readable name for operation"
@@ -286,6 +287,7 @@ def show_code(co, *, file=None):
286287_Instruction .line_number .__doc__ = "source line number associated with this opcode (if any), otherwise None"
287288_Instruction .label .__doc__ = "A label (int > 0) if this instruction is a jump target, otherwise None"
288289_Instruction .positions .__doc__ = "dis.Positions object holding the span of source code covered by this instruction"
290+ _Instruction .cache_info .__doc__ = "list of (name, size, data), one for each cache entry of the instruction"
289291
290292_ExceptionTableEntryBase = collections .namedtuple ("_ExceptionTableEntryBase" ,
291293 "start end target depth lasti" )
@@ -334,6 +336,8 @@ class Instruction(_Instruction):
334336 label - A label if this instruction is a jump target, otherwise None
335337 positions - Optional dis.Positions object holding the span of source code
336338 covered by this instruction
339+ cache_info - information about the format and content of the instruction's cache
340+ entries (if any)
337341 """
338342
339343 @property
@@ -570,7 +574,6 @@ def get_instructions(x, *, first_line=None, show_caches=False, adaptive=False):
570574 linestarts = linestarts ,
571575 line_offset = line_offset ,
572576 co_positions = co .co_positions (),
573- show_caches = show_caches ,
574577 original_code = original_code ,
575578 arg_resolver = arg_resolver )
576579
@@ -645,8 +648,7 @@ def _is_backward_jump(op):
645648 'ENTER_EXECUTOR' )
646649
647650def _get_instructions_bytes (code , linestarts = None , line_offset = 0 , co_positions = None ,
648- show_caches = False , original_code = None , labels_map = None ,
649- arg_resolver = None ):
651+ original_code = None , labels_map = None , arg_resolver = None ):
650652 """Iterate over the instructions in a bytecode string.
651653
652654 Generates a sequence of Instruction namedtuples giving the details of each
@@ -682,32 +684,28 @@ def _get_instructions_bytes(code, linestarts=None, line_offset=0, co_positions=N
682684 else :
683685 argval , argrepr = arg , repr (arg )
684686
687+ instr = Instruction (_all_opname [op ], op , arg , argval , argrepr ,
688+ offset , start_offset , starts_line , line_number ,
689+ labels_map .get (offset , None ), positions )
690+
691+ caches = _get_cache_size (_all_opname [deop ])
692+ # Advance the co_positions iterator:
693+ for _ in range (caches ):
694+ next (co_positions , ())
695+
696+ if caches :
697+ cache_info = []
698+ for name , size in _cache_format [opname [deop ]].items ():
699+ data = code [offset + 2 : offset + 2 + 2 * size ]
700+ cache_info .append ((name , size , data ))
701+ else :
702+ cache_info = None
703+
685704 yield Instruction (_all_opname [op ], op , arg , argval , argrepr ,
686705 offset , start_offset , starts_line , line_number ,
687- labels_map .get (offset , None ), positions )
706+ labels_map .get (offset , None ), positions , cache_info )
707+
688708
689- caches = _get_cache_size (_all_opname [deop ])
690- if not caches :
691- continue
692- if not show_caches :
693- # We still need to advance the co_positions iterator:
694- for _ in range (caches ):
695- next (co_positions , ())
696- continue
697- for name , size in _cache_format [opname [deop ]].items ():
698- for i in range (size ):
699- offset += 2
700- # Only show the fancy argrepr for a CACHE instruction when it's
701- # the first entry for a particular cache value:
702- if i == 0 :
703- data = code [offset : offset + 2 * size ]
704- argrepr = f"{ name } : { int .from_bytes (data , sys .byteorder )} "
705- else :
706- argrepr = ""
707- yield Instruction (
708- "CACHE" , CACHE , 0 , None , argrepr , offset , offset , False , None , None ,
709- Positions (* next (co_positions , ()))
710- )
711709
712710def disassemble (co , lasti = - 1 , * , file = None , show_caches = False , adaptive = False ,
713711 show_offsets = False ):
@@ -787,7 +785,6 @@ def _disassemble_bytes(code, lasti=-1, varname_from_oparg=None,
787785 instrs = _get_instructions_bytes (code , linestarts = linestarts ,
788786 line_offset = line_offset ,
789787 co_positions = co_positions ,
790- show_caches = show_caches ,
791788 original_code = original_code ,
792789 labels_map = labels_map ,
793790 arg_resolver = arg_resolver )
@@ -805,6 +802,23 @@ def print_instructions(instrs, exception_entries, formatter, show_caches=False,
805802 is_current_instr = instr .offset <= lasti \
806803 <= instr .offset + 2 * _get_cache_size (_all_opname [_deoptop (instr .opcode )])
807804 formatter .print_instruction (instr , is_current_instr )
805+ deop = _deoptop (instr .opcode )
806+ if show_caches and instr .cache_info :
807+ offset = instr .offset
808+ for name , size , data in instr .cache_info :
809+ for i in range (size ):
810+ offset += 2
811+ # Only show the fancy argrepr for a CACHE instruction when it's
812+ # the first entry for a particular cache value:
813+ if i == 0 :
814+ argrepr = f"{ name } : { int .from_bytes (data , sys .byteorder )} "
815+ else :
816+ argrepr = ""
817+ formatter .print_instruction (
818+ Instruction ("CACHE" , CACHE , 0 , None , argrepr , offset , offset ,
819+ False , None , None , instr .positions ),
820+ is_current_instr )
821+
808822 formatter .print_exception_table (exception_entries )
809823
810824def _disassemble_str (source , ** kwargs ):
@@ -952,7 +966,6 @@ def __iter__(self):
952966 linestarts = self ._linestarts ,
953967 line_offset = self ._line_offset ,
954968 co_positions = co .co_positions (),
955- show_caches = self .show_caches ,
956969 original_code = original_code ,
957970 labels_map = labels_map ,
958971 arg_resolver = arg_resolver )
0 commit comments