@@ -63,6 +63,7 @@ class Tier2Emitter(Emitter):
6363 def __init__ (self , out : CWriter , labels : dict [str , Label ]):
6464 super ().__init__ (out , labels )
6565 self ._replacers ["oparg" ] = self .oparg
66+ self ._replacers ["OFFSET_OF_CORRESPONDING_UOP" ] = self .offset_of_corresponding_uop
6667
6768 def goto_error (self , offset : int , storage : Storage ) -> str :
6869 # To do: Add jump targets for popping values.
@@ -134,6 +135,19 @@ def oparg(
134135 self .out .emit_at (uop .name [- 1 ], tkn )
135136 return True
136137
138+ def offset_of_corresponding_uop (
139+ self ,
140+ tkn : Token ,
141+ tkn_iter : TokenIterator ,
142+ uop : CodeSection ,
143+ storage : Storage ,
144+ inst : Instruction | None ,
145+ ) -> bool :
146+ assert uop .name .startswith ("_GUARD_IP" )
147+ rest = uop .name [len ("_GUARD_IP" ):]
148+ self .emit (f" OFFSET_OF{ rest } ;\n " )
149+ next (tkn_iter )
150+ return True
137151
138152def write_uop (uop : Uop , emitter : Emitter , stack : Stack ) -> Stack :
139153 locals : dict [str , Local ] = {}
@@ -165,33 +179,6 @@ def write_uop(uop: Uop, emitter: Emitter, stack: Stack) -> Stack:
165179SKIPS = ("_EXTENDED_ARG" ,)
166180
167181
168- def generate_guard_ips (
169- analysis : Analysis ,
170- emitter : Tier2Emitter ,
171- ) -> None :
172- for name , uop in analysis .uops .items ():
173- for stmt in uop .body .body :
174- tkn_iter = iter (stmt .tokens ())
175- for token in tkn_iter :
176- if token .kind == "IDENTIFIER" and token .text == "LOAD_IP" :
177- offset = []
178- while token .kind != "SEMI" :
179- offset .append (token .text )
180- token = next (tkn_iter )
181- # 1: to remove the LOAD_IP text
182- offset_str = "" .join (offset [1 :])
183- emitter .emit (f"case _GUARD_IP_{ name } : {{\n " )
184- emitter .emit ("PyObject *ip = (PyObject *)CURRENT_OPERAND0();\n " )
185- emitter .emit (f"if (frame->instr_ptr + { offset_str } != (_Py_CODEUNIT *)ip) {{\n " )
186- emitter .emit (f"frame->instr_ptr += { offset_str } ;\n " )
187- emitter .emit (f"UOP_STAT_INC(uopcode, miss);\n " )
188- emitter .emit ("JUMP_TO_JUMP_TARGET();\n " )
189- emitter .emit ("}\n " )
190- emitter .emit ("break;\n " )
191- emitter .emit ("}\n " )
192- emitter .emit ("\n " )
193-
194-
195182def generate_tier2 (
196183 filenames : list [str ], analysis : Analysis , outfile : TextIO , lines : bool
197184) -> None :
@@ -207,13 +194,35 @@ def generate_tier2(
207194 out = CWriter (outfile , 2 , lines )
208195 emitter = Tier2Emitter (out , analysis .labels )
209196 out .emit ("\n " )
197+ offset_strs : list [tuple [str , str ]] = []
198+ for name , uop in analysis .uops .items ():
199+ if not f"_GUARD_IP_{ name } " in analysis .uops :
200+ continue
201+ tkn_iter = uop .body .tokens ()
202+ found = False
203+ offset_str = ""
204+ for token in tkn_iter :
205+ if token .kind == "IDENTIFIER" and token .text == "LOAD_IP" :
206+ if found :
207+ raise analysis_error ("Cannot have two LOAD_IP in a guarded single uop." , uop .body .open )
208+ offset = []
209+ while token .kind != "SEMI" :
210+ offset .append (token .text )
211+ token = next (tkn_iter )
212+ # 1: to remove the LOAD_IP text
213+ offset_str = "" .join (offset [1 :])
214+ found = True
215+ assert offset_str
216+ out .emit (f"#define OFFSET_OF_{ name } ({ offset_str } )\n " )
217+ offset_strs .append ((name , offset_str ))
218+
219+ out .emit ("\n " )
220+
210221 for name , uop in analysis .uops .items ():
211222 if uop .properties .tier == 1 :
212223 continue
213224 if uop .is_super ():
214225 continue
215- if name .startswith ("_GUARD_IP" ):
216- continue
217226 why_not_viable = uop .why_not_viable ()
218227 if why_not_viable is not None :
219228 out .emit (
@@ -231,7 +240,9 @@ def generate_tier2(
231240 out .emit ("}" )
232241 out .emit ("\n \n " )
233242
234- generate_guard_ips (analysis , emitter )
243+ for name , offset_str in offset_strs :
244+ out .emit (f"#undef OFFSET_OF{ name } \n " )
245+ out .emit ("\n " )
235246 outfile .write ("#undef TIER_TWO\n " )
236247
237248
0 commit comments