@@ -115,7 +115,10 @@ def log(msg: str) -> None:
115115            # f"{root}-{pid}-{tslug}.out", 
116116        ]:
117117            with  open (filename , "a" ) as  f :
118-                 print (f"{ pid }  :{ tslug }  : { msg }  " , file = f , flush = True )
118+                 try :
119+                     print (f"{ pid }  :{ tslug }  : { msg }  " , file = f , flush = True )
120+                 except  UnicodeError :
121+                     print (f"{ pid }  :{ tslug }  : { ascii (msg )}  " , file = f , flush = True )
119122
120123    def  arg_repr (arg : Any ) ->  str :
121124        """Make a customized repr for logged values.""" 
@@ -214,6 +217,7 @@ def populate_branch_trails(code: CodeType, code_info: CodeInfo) -> None:
214217    """ 
215218    Populate the `branch_trails` attribute on `code_info`. 
216219    """ 
220+     log (f"populate_branch_trails: { code }  " )
217221    iwalker  =  InstructionWalker (code )
218222    for  inst  in  iwalker .walk (follow_jumps = False ):
219223        log (f"considering { inst = }  " )
@@ -225,7 +229,8 @@ def populate_branch_trails(code: CodeType, code_info: CodeInfo) -> None:
225229            continue 
226230
227231        from_line  =  inst .line_number 
228-         assert  from_line  is  not   None 
232+         if  from_line  is  None :
233+             continue 
229234
230235        def  walk_one_branch (
231236            start_at : TOffset , branch_kind : str 
@@ -255,14 +260,19 @@ def walk_one_branch(
255260                )
256261                return  inst_offsets , (from_line , to_line )
257262            else :
258-                 log (f"  no possible branch from @{ start_at }  : { inst_offsets }  " )
263+                 log (f"no possible branch from @{ start_at }  : { inst_offsets }  " )
259264                return  [], None 
260265
261-         code_info . branch_trails [ inst . offset ]  =  ( 
266+         trails  =  [ 
262267            walk_one_branch (start_at = inst .offset  +  2 , branch_kind = "not-taken" ),
263268            walk_one_branch (start_at = inst .jump_target , branch_kind = "taken" ),
264-         )
265- 
269+         ]
270+         code_info .branch_trails [inst .offset ] =  trails 
271+         for  trail  in  trails :
272+             for  offset  in  trail [0 ]:
273+                 if  offset  not  in   code_info .branch_trails :
274+                     code_info .branch_trails [offset ] =  []
275+                 code_info .branch_trails [offset ].append (trail )
266276
267277@dataclass  
268278class  CodeInfo :
@@ -272,18 +282,15 @@ class CodeInfo:
272282    file_data : TTraceFileData  |  None 
273283    byte_to_line : dict [TOffset , TLineNo ] |  None 
274284    # Keys are start instruction offsets for branches. 
275-     # Values are two tuples : 
276-     #   (  
285+     # Values are lists : 
286+     #   [  
277287    #       ([offset, offset, ...], (from_line, to_line)), 
278288    #       ([offset, offset, ...], (from_line, to_line)), 
279-     #   )  
289+     #   ]  
280290    #   Two possible trails from the branch point, left and right. 
281291    branch_trails : dict [
282292        TOffset ,
283-         tuple [
284-             tuple [list [TOffset ], TArc  |  None ],
285-             tuple [list [TOffset ], TArc  |  None ],
286-         ],
293+         list [tuple [list [TOffset ], TArc  |  None ]],
287294    ]
288295
289296
@@ -448,6 +455,7 @@ def sysmon_py_start(  # pylint: disable=useless-return
448455            )
449456            self .code_infos [id (code )] =  code_info 
450457            populate_branch_trails (code , code_info )  # TODO: should be a method? 
458+             log (f"branch_trails for { code }  :\n     { code_info .branch_trails }  " )
451459            self .code_objects .append (code )
452460
453461            if  tracing_code :
@@ -509,6 +517,7 @@ def sysmon_branch_either(
509517    ) ->  MonitorReturn :
510518        """Handle BRANCH_RIGHT and BRANCH_LEFT events.""" 
511519        code_info  =  self .code_infos [id (code )]
520+         added_arc  =  False 
512521        if  code_info .file_data  is  not   None :
513522            dest_info  =  code_info .branch_trails .get (instruction_offset )
514523            log (f"{ dest_info  =  }  " )
@@ -519,4 +528,17 @@ def sysmon_branch_either(
519528                    if  destination_offset  in  offsets :
520529                        cast (set [TArc ], code_info .file_data ).add (arc )
521530                        log (f"adding { arc = }  " )
531+                         added_arc  =  True 
532+                         break 
533+ 
534+         if  not  added_arc :
535+             # This could be an exception jumping from line to line. 
536+             assert  code_info .byte_to_line  is  not   None 
537+             l1  =  code_info .byte_to_line [instruction_offset ]
538+             l2  =  code_info .byte_to_line [destination_offset ]
539+             if  l1  !=  l2 :
540+                 arc  =  (l1 , l2 )
541+                 cast (set [TArc ], code_info .file_data ).add (arc )
542+                 log (f"adding unforeseen { arc = }  " )
543+ 
522544        return  DISABLE 
0 commit comments