diff options
author | Sam Gross <colesbury@gmail.com> | 2024-09-24 20:08:18 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-24 20:08:18 (GMT) |
commit | f4997bb3ac961d6aaf07ce650cd074e28ce6ccd0 (patch) | |
tree | 6c82b0fadd282e74c8f81de4a3966666fd210196 /Tools/cases_generator | |
parent | d3c76dff444046504754a437dceebc9a9c87ef18 (diff) | |
download | cpython-f4997bb3ac961d6aaf07ce650cd074e28ce6ccd0.zip cpython-f4997bb3ac961d6aaf07ce650cd074e28ce6ccd0.tar.gz cpython-f4997bb3ac961d6aaf07ce650cd074e28ce6ccd0.tar.bz2 |
gh-123923: Defer refcounting for `f_funcobj` in `_PyInterpreterFrame` (#124026)
Use a `_PyStackRef` and defer the reference to `f_funcobj` when
possible. This avoids some reference count contention in the common case
of executing the same code object from multiple threads concurrently in
the free-threaded build.
Diffstat (limited to 'Tools/cases_generator')
-rw-r--r-- | Tools/cases_generator/analyzer.py | 12 | ||||
-rw-r--r-- | Tools/cases_generator/generators_common.py | 9 |
2 files changed, 17 insertions, 4 deletions
diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py index 3cc36b6..0680c21 100644 --- a/Tools/cases_generator/analyzer.py +++ b/Tools/cases_generator/analyzer.py @@ -365,12 +365,24 @@ def analyze_deferred_refs(node: parser.InstDef) -> dict[lexer.Token, str | None] offset += 1 return [] + def in_frame_push(idx: int) -> bool: + for tkn in reversed(node.block.tokens[: idx - 1]): + if tkn.kind == "SEMI" or tkn.kind == "LBRACE" or tkn.kind == "RBRACE": + return False + if tkn.kind == "IDENTIFIER" and tkn.text == "_PyFrame_PushUnchecked": + return True + return False + refs: dict[lexer.Token, str | None] = {} for idx, tkn in enumerate(node.block.tokens): if tkn.kind != "IDENTIFIER" or tkn.text != "PyStackRef_FromPyObjectNew": continue if idx == 0 or node.block.tokens[idx - 1].kind != "EQUALS": + if in_frame_push(idx): + # PyStackRef_FromPyObjectNew() is called in _PyFrame_PushUnchecked() + refs[tkn] = None + continue raise analysis_error("Expected '=' before PyStackRef_FromPyObjectNew", tkn) lhs = find_assignment_target(idx) diff --git a/Tools/cases_generator/generators_common.py b/Tools/cases_generator/generators_common.py index 2f8fcce..4cfd4ad 100644 --- a/Tools/cases_generator/generators_common.py +++ b/Tools/cases_generator/generators_common.py @@ -200,15 +200,16 @@ class Emitter: stack: Stack, inst: Instruction | None, ) -> None: - self.out.emit(tkn) - emit_to(self.out, tkn_iter, "SEMI") - self.out.emit(";\n") - target = uop.deferred_refs[tkn] if target is None: # An assignment we don't handle, such as to a pointer or array. + self.out.emit(tkn) return + self.out.emit(tkn) + emit_to(self.out, tkn_iter, "SEMI") + self.out.emit(";\n") + # Flush the assignment to the stack. Note that we don't flush the # stack pointer here, and instead are currently relying on initializing # unused portions of the stack to NULL. |