o
    Ih_                     @   s  d Z ddlZddlZddlZddlZddlmZmZmZ ddl	m
Z
mZmZmZmZmZmZmZmZ ddlmZ dZdZdZd	Zd
ZdZdZdZdZdZdZdd Z d#ddZ!dd Z"ej#ddG dd dZ$ej#G dd dZ%dd Z&dd  Z'G d!d" d"Z(dS )$a  
This module provides functionality for resuming Python execution at specific points in code,
primarily used by PyTorch Dynamo for control flow handling and optimization. It implements
bytecode transformation and execution state management to enable:

- Resuming execution at arbitrary points in Python bytecode
- Managing context managers and their state across execution boundaries
- Transforming and generating new code objects with preserved execution state
- Supporting Python 3.11+ exception handling and block management
- Restoring torch function mode stacks and other execution context

The module is critical for PyTorch Dynamo's ability to optimize code while preserving
Python semantics and execution state.
    N)AnycastOptional   )	bytecode_from_templatecreate_call_functioncreate_instructioncreate_jump_absolutecreate_load_constInstructionoverwrite_instructiontransform_code_object	unique_id)ExactWeakKeyDictionary                @         i   torch_dynamo_resume_inc                 C   s@   t jdkr| td t jdk r| tddd d S d S d S )N      	PUSH_NULL)r      SWAPr   arg)sysversion_infoappendr   )insts r%   R/var/www/vscode/kcb/lib/python3.10/site-packages/torch/_dynamo/resume_execution.py_initial_push_null6   s   

r'   c                 C   s   t | |d}|td |D ]}|jr|j j|7  _qtdd t|D d\}}|d us1J t|tdg ||d  jdksDJ t||d  tdg |d |d  ||d d  fS )Nvarname_mapPOP_TOPc                 s   s0    | ]\}}|j d kr|jdkr||fV  qdS )	LOAD_FASTdummyNopnameargval).0iinstr%   r%   r&   	<genexpr>I   s    z5_bytecode_from_template_with_split.<locals>.<genexpr>)NNNOPr   )	r   r#   r   exn_tab_entrydepthnext	enumerater   r.   )templatestack_indexr)   template_coder2   	dummy_idx
dummy_instr%   r%   r&   "_bytecode_from_template_with_split>   s"    r>   c                 C   s   z|  W d S    t |  N)$__import_torch_dot__dynamo_dot_utilsset_torch_function_mode_stack)r,   stack_var_namer%   r%   r&   _try_except_tf_mode_template\   s   
rC   T)frozenc                   @   sZ   e Zd ZU eed< dZeeedf  ed< de	e
 fddZde	e
 fdd	Zd
d ZdS )ReenterWithr:   N.target_valuescleanupc                 C   s:   ddl m} tt| jd| id\}}|| |dd< |S )z
        Codegen based off of:
        try:
            (rest)
        except:
            (restore previous tf mode stack)
            raise
        r   )get_prev_stack_var_namerB   r(   N)variables.torch_functionrH   r>   rC   r:   )selfcode_optionsrG   rH   setup_try_exceptepiloguer%   r%   r&   try_except_torch_function_moden   s   	
z*ReenterWith.try_except_torch_function_modec           
      C   s   g }| j rdd | j D }td| j }||d vr$|d  |f7  < dD ]}||d vr7|d  |f7  < q&g }t| |g |tt|dtd|d	 d
d }t|| jd|id\}}	|	| |dd< || S )z
        Codegen based off of:
        load args
        enter context
        try:
            (rest)
        finally:
            exit context
        c                 S      g | ]}t |qS r%   r
   r0   valr%   r%   r&   
<listcomp>       z+ReenterWith.try_finally.<locals>.<listcomp>___context_manager_co_varnames	__enter____exit__co_namesF
STORE_FASTr/   c                 S   s2   |    z| W | d d d  d S | d d d  w r?   rW   ctxr,   r%   r%   r&   	_template   s   "z*ReenterWith.try_finally.<locals>._templater^   r(   N)	rF   r   r:   r'   extendr   lenr   r>   )
rJ   rK   rG   	load_argsctx_namename
create_ctxr_   setup_try_finallyrM   r%   r%   r&   try_finally   s6   

zReenterWith.try_finallyc                 C   s   g }| j rdd | j D }g }t| |g |tt|d dd }t|| j\}}|| |dd< tdd |D d}|dusEJ t|t	d	g d
d |D }	t|	d}
t|	ddu sbJ || |
fS )zR
        Codegen based off of:
        with ctx(args):
            (rest)
        c                 S   rO   r%   rP   rQ   r%   r%   r&   rS      rT   z(ReenterWith.__call__.<locals>.<listcomp>Fc                 S   s.   |  | W d    d S 1 sw   Y  d S r?   r%   r]   r%   r%   r&   r_      s   "z'ReenterWith.__call__.<locals>._templateNc                 s   s(    | ]}|j d kr|jdkr|V  qdS )r+   r^   Nr-   r0   r2   r%   r%   r&   r3      s    z'ReenterWith.__call__.<locals>.<genexpr>r4   c                 s   s    | ]
}|j d kr|V  qdS )PUSH_EXC_INFON)r.   rh   r%   r%   r&   r3      s    )
rF   r'   r`   r   ra   r>   r:   r7   r   r   )rJ   rK   rG   rb   re   r_   
setup_withrM   load_fast_ctx_instpush_exc_info_genpush_exc_info_instr%   r%   r&   __call__   s>   
zReenterWith.__call__)__name__
__module____qualname__int__annotations__rF   r   tupler   listr   rN   rg   rn   r%   r%   r%   r&   rE   i   s   
 ,rE   c                   @   s`   e Zd ZU ejed< ejedZ	ee
 ed< ejedZee ed< dZeeeef  ed< dS )ResumeFunctionMetadatacode)default_factoryinstructions prefix_block_target_offset_remapNblock_target_offset_remap)ro   rp   rq   typesCodeTypers   dataclassesfieldru   ry   r   rz   rr   r{   r   dictr%   r%   r%   r&   rv      s   
 
rv   c                 C   sV   t |}g }zt|}| D ]}|||r|| t|}qW |S  ty*   Y |S w )z
    Two-pointer conditional filter.
    e.g. _filter_iter(insts, sorted_offsets, lambda i, o: i.offset == o)
    returns the instructions with offsets in sorted_offsets
    )iterr7   r#   StopIteration)l1l2conditrescurrR   r%   r%   r&   _filter_iter   s   

r   c                 C   s8   g }t | |dd | D  |tt| d |S )Nc                 s   s    | ]}t |V  qd S r?   rP   rQ   r%   r%   r&   r3   
  s    z'_load_tuple_and_call.<locals>.<genexpr>F)r'   r`   r   ra   )tupr$   r%   r%   r&   _load_tuple_and_call  s
   r   c                   @   s   e Zd Ze Ze Zedd Zedede	edf dede	e
df de	e
df d	e	edf d
e	e	ee	e f df de	e	e
e	e f df de	edf dejfddZedee fddZedede	edf fddZdS )ContinueExecutionCachec                 G   sV   || j vr
i | j |< t|}|| j | vr$| j||g|R  | j | |< | j | | S r?   )cachert   generate)clsrw   linenokeyr%   r%   r&   lookup  s   

zContinueExecutionCache.lookupoffsetsetup_fn_target_offsets.nstackargnamesargnames_null	setup_fnsstack_ctx_varsargnames_ctx_vars
null_idxesreturnc                    s   	d usJ |j ttB tB tB @ rJ |j t@ sJ |tjv r.|	
 S t	j
dkt|dtt dtttf f 	
fdd}t||}tj|< |S )Nr   ry   rK   c                    sR  t | _dd t	D    fddD  t|d p!g t|d p(g  ttt d|d  d	 |d< rr|d
 jddd}t	|dkrW|d |d
< nt	|dks_J |\}}| dt d| d	 |d
< |d< d|d< |d< t	 |d< d|d< d|d< t  fddD   fdd|d D  |d< |d t
tB  @ |d< tfdd| D }g }r׈r|tdt	d |tddd g }dd D }fddtD }	d d | D }
i }d}t}t	D ]w}|t	
k r+
| || kr+|td! |d7 }|t	
k r+
| || ks|td"d#| d$ ||v rc||}|||\}}|| rc|	|}|
| }j| |||< || }||v ru|t||  qrttj_|rJ D ]\}}|td"|d$ |t| |td%|d$ qrtjd&ksJ D ]}| vsJ |td!td%|d$g q|t| | D ]}|j|jkr nd |_tjd'krd |_q|r|| || |rsJ | D ]}|jr|jj|v r||jj |j_q||  | d d < d S )(Nc                 S   s   g | ]}d | qS )___stackr%   r0   r1   r%   r%   r&   rS   F  s    zCContinueExecutionCache.generate.<locals>.update.<locals>.<listcomp>c                 3   s    | ]	}| vr|V  qd S r?   r%   r0   vargsr%   r&   r3   G  s    zBContinueExecutionCache.generate.<locals>.update.<locals>.<genexpr>co_cellvarsco_freevars_co_name_at_co_qualname.r   )maxsplitr   co_firstlinenor%   co_argcountr   co_posonlyargcountco_kwonlyargcountc                    s   g | ]}| vr|qS r%   r%   r   r   r%   r&   rS   a  s    c                    s    g | ]}| vr|vr|qS r%   r%   r   r   freevarsr%   r&   rS   b  s
    rV   co_flagsc                 3       | ]
}|j  kr|V  qd S r?   r   r   r   r%   r&   r3   k      COPY_FREE_VARSr   RESUMEc                 S      i | ]}|j |qS r%   r:   )r0   fnr%   r%   r&   
<dictcomp>v  rT   zCContinueExecutionCache.generate.<locals>.update.<locals>.<dictcomp>c                    s   i | ]
\}}|j  | qS r%   r   )r0   r1   r   )r   r%   r&   r   w  s    
c                 S   r   r%   r   rh   r%   r%   r&   r   {  rT   r   r+   r   r\   r[   )r      r   )copydeepcopyry   ranger`   rt   sortedTORCH_DYNAMO_RESUME_IN_PREFIXrsplitra   
CO_VARARGSCO_VARKEYWORDSr7   r#   r   r8   r   poprz   r   ru   reversedr!   r"   r	   r   starts_line	positionsunreachable_codesr5   target)ry   rK   qualified_pathmodule_namer   r   prefixrG   hookshook_target_offsetsoffset_to_instold_hook_target_remapnull_idxes_istack_ctx_vars_dr1   hook
hook_insts
exn_targethook_target_offsetold_hook_targetreal_ird   valsr   r2   r   r   r   r   is_py311_plusr   metar   r   r   r   r   r   r   r&   updateC  s   
	










z/ContinueExecutionCache.generate.<locals>.update)r   CO_GENERATORCO_COROUTINECO_ITERABLE_COROUTINECO_ASYNC_GENERATORCO_OPTIMIZEDr   generated_code_metadata&generate_based_on_original_code_objectr!   r"   rv   ru   r   r   strr   r   )r   rw   r   r   r   r   r   r   r   r   r   r   r   new_coder%   r   r&   r     s6   

: 

zContinueExecutionCache.generatec                 C   s   t dtdddgS )zACodegen a `raise None` to make analysis work for unreachable codeNRAISE_VARARGSr   r   )r
   r   )rK   r%   r%   r&   r     s   
z(ContinueExecutionCache.unreachable_codesc                    s   t j| ddtt dtttf ffdd}t|| tj	dkrOj
sDi   _
dtt dtttf f fdd}t|| tfd	d
D t jj|g|R  S )a>  
        This handles the case of generating a resume into code generated
        to resume something else.  We want to always generate starting
        from the original code object so that if control flow paths
        converge we only generated 1 resume function (rather than 2^n
        resume functions).
        Nry   rK   c                    sR   fdd| D \  fddt t| tjD \} j|jks$J |jd S )Nc                 3   r   r?   r   r   r   r%   r&   r3     r   ziContinueExecutionCache.generate_based_on_original_code_object.<locals>.find_new_offset.<locals>.<genexpr>c                 3   s     | ]\}}| u r|V  qd S r?   r%   )r0   i1i2r   r%   r&   r3     s    )zipr   ry   opcoder   )ry   rK   
new_target)r   
new_offsetr   r   r&   find_new_offset  s   

zVContinueExecutionCache.generate_based_on_original_code_object.<locals>.find_new_offsetr   c           
         s   g }| D ]}t |t jkr n|jdkr|| qt|jD ]\}}|tt|j< q"|r9tt|d jnd t fddD }t	| |dd }t	tt
| t
j|dd }t||D ]\}}	|d j|	j< qcd S )	Nri   c                 3   s    | ]	}| kr|V  qd S r?   r%   r0   nold_start_offsetr%   r&   r3   #  s    zmContinueExecutionCache.generate_based_on_original_code_object.<locals>.remap_block_offsets.<locals>.<genexpr>c                 S   s
   | j |kS r?   r   )r2   or%   r%   r&   <lambda>'  s   
 zlContinueExecutionCache.generate_based_on_original_code_object.<locals>.remap_block_offsets.<locals>.<lambda>c                 S   s   | d |u S )Nr   r%   )v1v2r%   r%   r&   r   ,  s    r   )ra   rz   r.   r#   r   r   rr   r   r   r   r   ry   )
ry   rK   prefix_blocksr2   r   old_inst_offsetstargetsnew_targetsnewold)r{   r   r   r   r&   remap_block_offsets  s:   


zZContinueExecutionCache.generate_based_on_original_code_object.<locals>.remap_block_offsetsc                 3   s    | ]} j | V  qd S r?   )r{   r   )r   r%   r&   r3   4  s    

zPContinueExecutionCache.generate_based_on_original_code_object.<locals>.<genexpr>)r   r   ru   r   r   r   r   r   r!   r"   r{   rt   r   rw   )r   rw   r   r   r   r   r   r   r%   )r{   r   r   r   r   r&   r     s6   





*
z=ContinueExecutionCache.generate_based_on_original_code_objectN)ro   rp   rq   r   r   r   classmethodr   rr   rt   r   rE   r   r|   r}   r   staticmethodru   r   r   r   r%   r%   r%   r&   r     sH    




	

 :
r   r?   ))__doc__r   r~   r!   r|   typingr   r   r   bytecode_transformationr   r   r   r	   r
   r   r   r   r   utilsr   r   CO_NEWLOCALSr   r   	CO_NESTEDr   	CO_NOFREEr   r   r   r   r'   r>   rC   	dataclassrE   rv   r   r   r   r%   r%   r%   r&   <module>   s@   ,

z  /