Skip to content

Commit ceab11b

Browse files
committed
gh-115999: Add partial free-thread specialzation for BINARY_SUBSCR
1 parent cc813e1 commit ceab11b

File tree

5 files changed

+42
-20
lines changed

5 files changed

+42
-20
lines changed

Python/bytecodes.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,7 @@ dummy_func(
704704
};
705705

706706
specializing op(_SPECIALIZE_BINARY_SUBSCR, (counter/1, container, sub -- container, sub)) {
707-
#if ENABLE_SPECIALIZATION
707+
#if ENABLE_SPECIALIZATION_FT
708708
assert(frame->stackpointer == NULL);
709709
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
710710
next_instr = this_instr;
@@ -713,7 +713,7 @@ dummy_func(
713713
}
714714
OPCODE_DEFERRED_INC(BINARY_SUBSCR);
715715
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
716-
#endif /* ENABLE_SPECIALIZATION */
716+
#endif /* ENABLE_SPECIALIZATION_FT */
717717
}
718718

719719
op(_BINARY_SUBSCR, (container, sub -- res)) {
@@ -790,10 +790,15 @@ dummy_func(
790790
// Deopt unless 0 <= sub < PyList_Size(list)
791791
DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub));
792792
Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];
793-
DEOPT_IF(index >= PyList_GET_SIZE(list));
793+
DEOPT_IF(!LOCK_OBJECT(list));
794+
if (index >= PyList_GET_SIZE(list)) {
795+
UNLOCK_OBJECT(list);
796+
DEOPT_IF(true);
797+
}
794798
STAT_INC(BINARY_SUBSCR, hit);
795799
PyObject *res_o = PyList_GET_ITEM(list, index);
796800
assert(res_o != NULL);
801+
UNLOCK_OBJECT(list);
797802
Py_INCREF(res_o);
798803
PyStackRef_CLOSE_SPECIALIZED(sub_st, (destructor)PyObject_Free);
799804
DEAD(sub_st);

Python/ceval_macros.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,13 @@ GETITEM(PyObject *v, Py_ssize_t i) {
295295
dtrace_function_entry(frame); \
296296
}
297297

298+
#ifdef Py_GIL_DISABLED
299+
# define LOCK_OBJECT(op) PyMutex_LockFast(&(_PyObject_CAST(op))->ob_mutex._bits)
300+
# define UNLOCK_OBJECT(op) PyMutex_Unlock(&(_PyObject_CAST(op))->ob_mutex)
301+
#else
302+
# define LOCK_OBJECT(op) (1)
303+
# define UNLOCK_OBJECT(op) ((void)0)
304+
#endif
298305
/* This takes a uint16_t instead of a _Py_BackoffCounter,
299306
* because it is used directly on the cache entry in generated code,
300307
* which is always an integral type. */

Python/executor_cases.c.h

Lines changed: 9 additions & 1 deletion
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: 8 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/specialize.c

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,12 +1720,12 @@ _Py_Specialize_BinarySubscr(
17201720
assert(ENABLE_SPECIALIZATION);
17211721
assert(_PyOpcode_Caches[BINARY_SUBSCR] ==
17221722
INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
1723-
_PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)(instr + 1);
17241723
PyTypeObject *container_type = Py_TYPE(container);
1724+
uint8_t specialized_op;
17251725
if (container_type == &PyList_Type) {
17261726
if (PyLong_CheckExact(sub)) {
17271727
if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) {
1728-
instr->op.code = BINARY_SUBSCR_LIST_INT;
1728+
specialized_op = BINARY_SUBSCR_LIST_INT;
17291729
goto success;
17301730
}
17311731
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
@@ -1738,7 +1738,7 @@ _Py_Specialize_BinarySubscr(
17381738
if (container_type == &PyTuple_Type) {
17391739
if (PyLong_CheckExact(sub)) {
17401740
if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) {
1741-
instr->op.code = BINARY_SUBSCR_TUPLE_INT;
1741+
specialized_op = BINARY_SUBSCR_TUPLE_INT;
17421742
goto success;
17431743
}
17441744
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
@@ -1751,7 +1751,7 @@ _Py_Specialize_BinarySubscr(
17511751
if (container_type == &PyUnicode_Type) {
17521752
if (PyLong_CheckExact(sub)) {
17531753
if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) {
1754-
instr->op.code = BINARY_SUBSCR_STR_INT;
1754+
specialized_op = BINARY_SUBSCR_STR_INT;
17551755
goto success;
17561756
}
17571757
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
@@ -1762,9 +1762,10 @@ _Py_Specialize_BinarySubscr(
17621762
goto fail;
17631763
}
17641764
if (container_type == &PyDict_Type) {
1765-
instr->op.code = BINARY_SUBSCR_DICT;
1765+
specialized_op = BINARY_SUBSCR_DICT;
17661766
goto success;
17671767
}
1768+
#ifndef Py_GIL_DISABLED
17681769
PyTypeObject *cls = Py_TYPE(container);
17691770
PyObject *descriptor = _PyType_Lookup(cls, &_Py_ID(__getitem__));
17701771
if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
@@ -1797,21 +1798,17 @@ _Py_Specialize_BinarySubscr(
17971798
// struct _specialization_cache):
17981799
ht->_spec_cache.getitem = descriptor;
17991800
ht->_spec_cache.getitem_version = version;
1800-
instr->op.code = BINARY_SUBSCR_GETITEM;
1801+
specialized_op = BINARY_SUBSCR_GETITEM;
18011802
goto success;
18021803
}
1804+
#endif // Py_GIL_DISABLED
18031805
SPECIALIZATION_FAIL(BINARY_SUBSCR,
18041806
binary_subscr_fail_kind(container_type, sub));
18051807
fail:
1806-
STAT_INC(BINARY_SUBSCR, failure);
1807-
assert(!PyErr_Occurred());
1808-
instr->op.code = BINARY_SUBSCR;
1809-
cache->counter = adaptive_counter_backoff(cache->counter);
1808+
unspecialize(instr);
18101809
return;
18111810
success:
1812-
STAT_INC(BINARY_SUBSCR, success);
1813-
assert(!PyErr_Occurred());
1814-
cache->counter = adaptive_counter_cooldown();
1811+
specialize(instr, specialized_op);
18151812
}
18161813

18171814
void

0 commit comments

Comments
 (0)