Skip to content

Commit c05c547

Browse files
committed
Whitelist non-esacping dealloc functions
1 parent 74f69b8 commit c05c547

File tree

1 file changed

+62
-19
lines changed

1 file changed

+62
-19
lines changed

Tools/cases_generator/generators_common.py

Lines changed: 62 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ def always_true(tkn: Token | None) -> bool:
9898
return False
9999
return tkn.text in {"true", "1"}
100100

101+
NON_ESCAPING_DEALLOCS = {
102+
"_PyFloat_ExactDealloc",
103+
"_PyLong_ExactDealloc",
104+
"_PyUnicode_ExactDealloc",
105+
}
101106

102107
class Emitter:
103108
out: CWriter
@@ -116,7 +121,7 @@ def __init__(self, out: CWriter):
116121
"SAVE_STACK": self.save_stack,
117122
"RELOAD_STACK": self.reload_stack,
118123
"PyStackRef_CLOSE": self.stackref_close,
119-
"PyStackRef_CLOSE_SPECIALIZED": self.stackref_close_no_escape,
124+
"PyStackRef_CLOSE_SPECIALIZED": self.stackref_close_specialized,
120125
"PyStackRef_AsPyObjectSteal": self.stackref_steal,
121126
"DISPATCH": self.dispatch,
122127
"INSTRUCTION_SIZE": self.instruction_size,
@@ -295,11 +300,31 @@ def kill(
295300
return True
296301

297302
def stackref_kill(
303+
self,
304+
name: Token,
305+
storage: Storage,
306+
escapes: bool
307+
) -> bool:
308+
live = ""
309+
for var in reversed(storage.inputs):
310+
if var.name == name.text:
311+
if live and escapes:
312+
raise analysis_error(
313+
f"Cannot close '{name.text}' when "
314+
f"'{live}' is still live", name)
315+
var.defined = False
316+
break
317+
if var.defined:
318+
live = var.name
319+
return True
320+
321+
def stackref_close(
298322
self,
299323
tkn: Token,
300324
tkn_iter: TokenIterator,
325+
uop: Uop,
301326
storage: Storage,
302-
escapes: bool
327+
inst: Instruction | None,
303328
) -> bool:
304329
self.out.emit(tkn)
305330
tkn = next(tkn_iter)
@@ -308,42 +333,60 @@ def stackref_kill(
308333
name = next(tkn_iter)
309334
self.out.emit(name)
310335
if name.kind == "IDENTIFIER":
311-
live = ""
312-
for var in reversed(storage.inputs):
313-
if var.name == name.text:
314-
if live and escapes:
315-
raise analysis_error(
316-
f"Cannot close '{name.text}' when "
317-
f"'{live}' is still live", name)
318-
var.defined = False
319-
break
320-
if var.defined:
321-
live = var.name
336+
return self.stackref_kill(name, storage, True)
322337
rparen = emit_to(self.out, tkn_iter, "RPAREN")
323338
self.emit(rparen)
324339
return True
325340

326-
def stackref_close(
341+
def stackref_close_specialized(
327342
self,
328343
tkn: Token,
329344
tkn_iter: TokenIterator,
330345
uop: Uop,
331346
storage: Storage,
332347
inst: Instruction | None,
333348
) -> bool:
334-
return self.stackref_kill(tkn, tkn_iter, storage, True)
335349

336-
def stackref_close_no_escape(
350+
self.out.emit(tkn)
351+
tkn = next(tkn_iter)
352+
assert tkn.kind == "LPAREN"
353+
self.out.emit(tkn)
354+
name = next(tkn_iter)
355+
self.out.emit(name)
356+
comma = next(tkn_iter)
357+
if comma.kind != "COMMA":
358+
raise analysis_error("Expected comma", comma)
359+
self.out.emit(comma)
360+
dealloc = next(tkn_iter)
361+
if dealloc.kind != "IDENTIFIER":
362+
raise analysis_error("Expected identifier", dealloc)
363+
self.out.emit(dealloc)
364+
if name.kind == "IDENTIFIER":
365+
escapes = dealloc.text not in NON_ESCAPING_DEALLOCS
366+
return self.stackref_kill(name, storage, escapes)
367+
rparen = emit_to(self.out, tkn_iter, "RPAREN")
368+
self.emit(rparen)
369+
return True
370+
371+
def stackref_steal(
337372
self,
338373
tkn: Token,
339374
tkn_iter: TokenIterator,
340375
uop: Uop,
341376
storage: Storage,
342377
inst: Instruction | None,
343378
) -> bool:
344-
return self.stackref_kill(tkn, tkn_iter, storage, False)
345-
346-
stackref_steal = stackref_close_no_escape
379+
self.out.emit(tkn)
380+
tkn = next(tkn_iter)
381+
assert tkn.kind == "LPAREN"
382+
self.out.emit(tkn)
383+
name = next(tkn_iter)
384+
self.out.emit(name)
385+
if name.kind == "IDENTIFIER":
386+
return self.stackref_kill(name, storage, False)
387+
rparen = emit_to(self.out, tkn_iter, "RPAREN")
388+
self.emit(rparen)
389+
return True
347390

348391
def sync_sp(
349392
self,

0 commit comments

Comments
 (0)