Skip to content

Commit c84928e

Browse files
authored
gh-115999: Specialize CALL_KW in free-threaded builds (#127713)
* Enable specialization of CALL_KW * Fix bug pushing frame in _PY_FRAME_KW `_PY_FRAME_KW` pushes a pointer to the new frame onto the stack for consumption by the next uop. When pushing the frame fails, we do not want to push the result, `NULL`, to the stack because it is not a valid stackref. This works in the default build because `PyStackRef_NULL` and `NULL` are the same value, so the `PyStackRef_XCLOSE()` in the error handler ignores it. In the free-threaded build the values are not the same; `PyStackRef_XCLOSE()` will attempt to decref a null pointer.
1 parent e8f4e27 commit c84928e

File tree

4 files changed

+26
-35
lines changed

4 files changed

+26
-35
lines changed

Python/bytecodes.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4311,17 +4311,18 @@ dummy_func(
43114311
assert(Py_TYPE(callable_o) == &PyFunction_Type);
43124312
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
43134313
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
4314-
new_frame = _PyEvalFramePushAndInit(
4314+
_PyInterpreterFrame *temp = _PyEvalFramePushAndInit(
43154315
tstate, callable[0], locals,
43164316
args, positional_args, kwnames_o, frame
43174317
);
43184318
PyStackRef_CLOSE(kwnames);
43194319
// The frame has stolen all the arguments from the stack,
43204320
// so there is no need to clean them up.
43214321
SYNC_SP();
4322-
if (new_frame == NULL) {
4322+
if (temp == NULL) {
43234323
ERROR_NO_POP();
43244324
}
4325+
new_frame = temp;
43254326
}
43264327

43274328
op(_CHECK_FUNCTION_VERSION_KW, (func_version/2, callable[1], self_or_null[1], unused[oparg], kwnames -- callable[1], self_or_null[1], unused[oparg], kwnames)) {
@@ -4372,15 +4373,15 @@ dummy_func(
43724373
_PUSH_FRAME;
43734374

43744375
specializing op(_SPECIALIZE_CALL_KW, (counter/1, callable[1], self_or_null[1], args[oparg], kwnames -- callable[1], self_or_null[1], args[oparg], kwnames)) {
4375-
#if ENABLE_SPECIALIZATION
4376+
#if ENABLE_SPECIALIZATION_FT
43764377
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
43774378
next_instr = this_instr;
43784379
_Py_Specialize_CallKw(callable[0], next_instr, oparg + !PyStackRef_IsNull(self_or_null[0]));
43794380
DISPATCH_SAME_OPARG();
43804381
}
43814382
OPCODE_DEFERRED_INC(CALL_KW);
43824383
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
4383-
#endif /* ENABLE_SPECIALIZATION */
4384+
#endif /* ENABLE_SPECIALIZATION_FT */
43844385
}
43854386

43864387
macro(CALL_KW) =

Python/executor_cases.c.h

Lines changed: 7 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 10 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/specialize.c

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2107,7 +2107,7 @@ specialize_py_call_kw(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
21072107
return -1;
21082108
}
21092109
write_u32(cache->func_version, version);
2110-
instr->op.code = bound_method ? CALL_KW_BOUND_METHOD : CALL_KW_PY;
2110+
specialize(instr, bound_method ? CALL_KW_BOUND_METHOD : CALL_KW_PY);
21112111
return 0;
21122112
}
21132113

@@ -2202,10 +2202,9 @@ _Py_Specialize_CallKw(_PyStackRef callable_st, _Py_CODEUNIT *instr, int nargs)
22022202
{
22032203
PyObject *callable = PyStackRef_AsPyObjectBorrow(callable_st);
22042204

2205-
assert(ENABLE_SPECIALIZATION);
2205+
assert(ENABLE_SPECIALIZATION_FT);
22062206
assert(_PyOpcode_Caches[CALL_KW] == INLINE_CACHE_ENTRIES_CALL_KW);
22072207
assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL_KW);
2208-
_PyCallCache *cache = (_PyCallCache *)(instr + 1);
22092208
int fail;
22102209
if (PyFunction_Check(callable)) {
22112210
fail = specialize_py_call_kw((PyFunctionObject *)callable, instr, nargs, false);
@@ -2221,19 +2220,11 @@ _Py_Specialize_CallKw(_PyStackRef callable_st, _Py_CODEUNIT *instr, int nargs)
22212220
}
22222221
}
22232222
else {
2224-
instr->op.code = CALL_KW_NON_PY;
2223+
specialize(instr, CALL_KW_NON_PY);
22252224
fail = 0;
22262225
}
22272226
if (fail) {
2228-
STAT_INC(CALL, failure);
2229-
assert(!PyErr_Occurred());
2230-
instr->op.code = CALL_KW;
2231-
cache->counter = adaptive_counter_backoff(cache->counter);
2232-
}
2233-
else {
2234-
STAT_INC(CALL, success);
2235-
assert(!PyErr_Occurred());
2236-
cache->counter = adaptive_counter_cooldown();
2227+
unspecialize(instr);
22372228
}
22382229
}
22392230

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy