Skip to content

Commit d7f7da9

Browse files
committed
Avoid locking in _LOAD_ATTR_WITH_HINT
1 parent b92ee14 commit d7f7da9

File tree

5 files changed

+61
-41
lines changed

5 files changed

+61
-41
lines changed

Include/internal/pycore_dict.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,10 @@ extern int _PyDict_Pop_KnownHash(
150150
Py_hash_t hash,
151151
PyObject **result);
152152

153+
#ifdef Py_GIL_DISABLED
154+
PyAPI_FUNC(void) _PyDict_EnsureSharedOnRead(PyDictObject *mp);
155+
#endif
156+
153157
#define DKIX_EMPTY (-1)
154158
#define DKIX_DUMMY (-2) /* Used internally */
155159
#define DKIX_ERROR (-3)

Objects/dictobject.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,12 @@ ensure_shared_on_read(PyDictObject *mp)
13251325
Py_END_CRITICAL_SECTION();
13261326
}
13271327
}
1328+
1329+
void
1330+
_PyDict_EnsureSharedOnRead(PyDictObject *mp)
1331+
{
1332+
ensure_shared_on_read(mp);
1333+
}
13281334
#endif
13291335

13301336
static inline void

Python/bytecodes.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2285,34 +2285,36 @@ dummy_func(
22852285
assert(Py_TYPE(owner_o)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
22862286
PyDictObject *dict = _PyObject_GetManagedDict(owner_o);
22872287
DEOPT_IF(dict == NULL);
2288+
PyDictKeysObject *dk = FT_ATOMIC_LOAD_PTR(dict->ma_keys);
22882289
assert(PyDict_CheckExact((PyObject *)dict));
2290+
#ifdef Py_GIL_DISABLED
2291+
_PyDict_EnsureSharedOnRead(dict);
2292+
#endif
22892293
PyObject *attr_o;
2290-
if (!LOCK_OBJECT(dict)) {
2294+
if (hint >= (size_t)FT_ATOMIC_LOAD_SSIZE_RELAXED(dk->dk_nentries)) {
22912295
DEOPT_IF(true);
22922296
}
22932297

2294-
if (hint >= (size_t)dict->ma_keys->dk_nentries) {
2295-
UNLOCK_OBJECT(dict);
2296-
DEOPT_IF(true);
2297-
}
22982298
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
2299-
if (dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {
2300-
UNLOCK_OBJECT(dict);
2299+
if (dk->dk_kind != DICT_KEYS_UNICODE) {
23012300
DEOPT_IF(true);
23022301
}
2303-
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
2304-
if (ep->me_key != name) {
2305-
UNLOCK_OBJECT(dict);
2302+
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dk) + hint;
2303+
if (FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_key) != name) {
23062304
DEOPT_IF(true);
23072305
}
2308-
attr_o = ep->me_value;
2306+
attr_o = FT_ATOMIC_LOAD_PTR(ep->me_value);
23092307
if (attr_o == NULL) {
2310-
UNLOCK_OBJECT(dict);
23112308
DEOPT_IF(true);
23122309
}
23132310
STAT_INC(LOAD_ATTR, hit);
2311+
#ifdef Py_GIL_DISABLED
2312+
if (!_Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr)) {
2313+
DEOPT_IF(true);
2314+
}
2315+
#else
23142316
attr = PyStackRef_FromPyObjectNew(attr_o);
2315-
UNLOCK_OBJECT(dict);
2317+
#endif
23162318
PyStackRef_CLOSE(owner);
23172319
}
23182320

Python/executor_cases.c.h

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

0 commit comments

Comments
 (0)