o
    Zh_                     @   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   Z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      ZSWAPr   arg)sysversion_infoappendr   )insts r#   M/var/www/auris/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'   Ztemplate_coder0   Z	dummy_idxZ
dummy_instr#   r#   r$   "_bytecode_from_template_with_split>   s"    r9   c                 C   s   z|  W d S    t |  N)Z$__import_torch_dot__dynamo_dot_utilsZset_torch_function_mode_stack)r*   stack_var_namer#   r#   r$   _try_except_tf_mode_template\   s   
r<   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 )ReenterWithr8   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_namer;   r&   N)Zvariables.torch_functionrA   r9   r<   r8   )selfcode_optionsr@   rA   Z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
   r.   valr#   r#   r$   
<listcomp>       z+ReenterWith.try_finally.<locals>.<listcomp>Z___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:   rM   ctxr*   r#   r#   r$   	_template   s   "z*ReenterWith.try_finally.<locals>._templaterT   r&   N)	r?   r   r8   r%   extendr   lenr   r9   )
rB   rC   r@   	load_argsZctx_namename
create_ctxrU   Zsetup_try_finallyrD   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   rF   r#   rG   rH   r#   r#   r$   rJ      rK   z(ReenterWith.__call__.<locals>.<listcomp>Fc                 S   s.   |  | W d    d S 1 sw   Y  d S r:   r#   rS   r#   r#   r$   rU      s   "z'ReenterWith.__call__.<locals>._templateNc                 s   s(    | ]}|j d kr|jdkr|V  qdS )r)   rT   Nr+   r.   r0   r#   r#   r$   r1      s    z'ReenterWith.__call__.<locals>.<genexpr>r2   c                 s   s    | ]
}|j d kr|V  qdS )PUSH_EXC_INFON)r,   r\   r#   r#   r$   r1      s    )
r?   r%   rV   r   rW   r9   r8   r5   r   r   )rB   rC   r@   rX   rZ   rU   Z
setup_withrD   Zload_fast_ctx_instZpush_exc_info_genZpush_exc_info_instr#   r#   r$   __call__   s>   
zReenterWith.__call__)__name__
__module____qualname__int__annotations__r?   r   tupler   listr   rE   r[   r^   r#   r#   r#   r$   r>   i   s   
 ,r>   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)r_   r`   ra   typesCodeTyperc   dataclassesfieldre   ri   r   rj   rb   rk   r   dictr#   r#   r#   r$   rf      s   
 
rf   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
    )iterr5   r!   StopIteration)l1l2ZconditrescurrI   r#   r#   r$   _filter_iter   s   

rx   c                 C   s8   g }t | |dd | D  |tt| d |S )Nc                 s   s    | ]}t |V  qd S r:   rG   rH   r#   r#   r$   r1   
  s    z'_load_tuple_and_call.<locals>.<genexpr>F)r%   rV   r   rW   )tupr"   r#   r#   r$   _load_tuple_and_call  s
   rz   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:   )cacherd   generate)clsrg   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   ri   rC   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#   r.   r/   r#   r#   r$   rJ   F  s    zCContinueExecutionCache.generate.<locals>.update.<locals>.<listcomp>c                 3   s    | ]	}| vr|V  qd S r:   r#   r.   vargsr#   r$   r1   G  s    zBContinueExecutionCache.generate.<locals>.update.<locals>.<genexpr>co_cellvarsco_freevars_co_nameZ_at_Zco_qualname.r   )maxsplitr   co_firstlinenor#   co_argcountr   co_posonlyargcountco_kwonlyargcountc                    s   g | ]}| vr|qS r#   r#   r   r   r#   r$   rJ   a  s    c                    s    g | ]}| vr|vr|qS r#   r#   r   r   Zfreevarsr#   r$   rJ   b  s
    rL   co_flagsc                 3       | ]
}|j  kr|V  qd S r:   r   r   r   r#   r$   r1   k      ZCOPY_FREE_VARSr   RESUMEc                 S      i | ]}|j |qS r#   r8   )r.   fnr#   r#   r$   
<dictcomp>v  rK   zCContinueExecutionCache.generate.<locals>.update.<locals>.<dictcomp>c                    s   i | ]
\}}|j  | qS r#   r   )r.   r/   r   )r   r#   r$   r   w  s    
c                 S   r   r#   r   r\   r#   r#   r$   r   {  rK   r   r)   r   rR   rQ   )r      r   )copydeepcopyri   rangerV   rd   sortedTORCH_DYNAMO_RESUME_IN_PREFIXrsplitrW   
CO_VARARGSCO_VARKEYWORDSr5   r!   r   r6   rp   poprj   rz   re   reversedr   r    r	   r   starts_lineZ	positionsunreachable_codesr3   target)ri   rC   Zqualified_pathmodule_namer   r   prefixr@   hooksZhook_target_offsetsZoffset_to_instZold_hook_target_remapZnull_idxes_iZstack_ctx_vars_dr/   hookZ
hook_instsZ
exn_targetZhook_target_offsetZold_hook_targetZreal_irY   valsr   r0   r   r   r   r~   Z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    rf   re   r   rp   strr   r   )r~   rg   r   r   r   r   r   r   r   r   r   r   r   Z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   )rC   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).
        Nri   rC   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$   r1     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#   )r.   i1i2r   r#   r$   r1     s    )zipr   ri   opcoder   )ri   rC   
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 )	Nr]   c                 3   s    | ]	}| kr|V  qd S r:   r#   r.   nZold_start_offsetr#   r$   r1   #  s    zmContinueExecutionCache.generate_based_on_original_code_object.<locals>.remap_block_offsets.<locals>.<genexpr>c                 S   s
   | j |kS r:   r   )r0   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   )rW   rj   r,   r!   r   r   rb   r   r   rx   r   ri   )
ri   rC   Zprefix_blocksr0   r   Zold_inst_offsetstargetsZnew_targetsnewold)rk   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:   )rk   r   )r   r#   r$   r1   4  s    

zPContinueExecutionCache.generate_based_on_original_code_object.<locals>.<genexpr>)r{   r   re   r   rp   r   r   r   r   r    rk   rd   r   rg   )r~   rg   r   r   r   r   r   r   r#   )rk   r   r   r   r   r$   r     s6   





*
z=ContinueExecutionCache.generate_based_on_original_code_objectN)r_   r`   ra   r   r|   r   classmethodr   rb   rd   r   r>   r   rl   rm   r}   staticmethodre   r   r   r   r#   r#   r#   r$   r{     sH    




	

 :
r{   r:   ))__doc__r   rn   r   rl   typingr   r   r   Zbytecode_transformationr   r   r   r	   r
   r   r   r   r   utilsr   r   ZCO_NEWLOCALSr   r   	CO_NESTEDr   Z	CO_NOFREEr   r   r   r   r%   r9   r<   	dataclassr>   rf   rx   rz   r{   r#   r#   r#   r$   <module>   s@   ,

z  /