Skip to content

Commit 6f8b1d7

Browse files
committed
Avoid locking in _LOAD_ATTR_WITH_HINT
1 parent ccf1732 commit 6f8b1d7

File tree

7 files changed

+64
-45
lines changed

7 files changed

+64
-45
lines changed

Include/internal/pycore_dict.h

+4
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ extern int _PyDict_Pop_KnownHash(
149149
Py_hash_t hash,
150150
PyObject **result);
151151

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

Include/internal/pycore_opcode_metadata.h

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_metadata.h

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Objects/dictobject.c

+6
Original file line numberDiff line numberDiff line change
@@ -1323,6 +1323,12 @@ ensure_shared_on_read(PyDictObject *mp)
13231323
Py_END_CRITICAL_SECTION();
13241324
}
13251325
}
1326+
1327+
void
1328+
_PyDict_EnsureSharedOnRead(PyDictObject *mp)
1329+
{
1330+
ensure_shared_on_read(mp);
1331+
}
13261332
#endif
13271333

13281334
static inline void

Python/bytecodes.c

+16-15
Original file line numberDiff line numberDiff line change
@@ -2282,42 +2282,43 @@ dummy_func(
22822282
PyDictObject *dict_o = _PyObject_GetManagedDict(owner_o);
22832283
EXIT_IF(dict_o == NULL);
22842284
assert(PyDict_CheckExact((PyObject *)dict_o));
2285+
#ifdef Py_GIL_DISABLED
2286+
_PyDict_EnsureSharedOnRead(dict_o);
2287+
#endif
22852288
dict = dict_o;
22862289
}
22872290

22882291
op(_LOAD_ATTR_WITH_HINT, (hint/1, owner, dict: PyDictObject * -- attr)) {
2292+
PyDictKeysObject *dk = FT_ATOMIC_LOAD_PTR(dict->ma_keys);
22892293
PyObject *attr_o;
2290-
if (!LOCK_OBJECT(dict)) {
2294+
if (hint >= (size_t)dk->dk_nentries) {
22912295
POP_INPUT(dict);
22922296
DEOPT_IF(true);
22932297
}
2294-
2295-
if (hint >= (size_t)dict->ma_keys->dk_nentries) {
2296-
UNLOCK_OBJECT(dict);
2298+
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
2299+
if (dk->dk_kind != DICT_KEYS_UNICODE) {
22972300
POP_INPUT(dict);
22982301
DEOPT_IF(true);
22992302
}
2300-
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
2301-
if (dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {
2302-
UNLOCK_OBJECT(dict);
2303+
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dk) + hint;
2304+
if (FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_key) != name) {
23032305
POP_INPUT(dict);
23042306
DEOPT_IF(true);
23052307
}
2306-
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
2307-
if (ep->me_key != name) {
2308-
UNLOCK_OBJECT(dict);
2308+
attr_o = FT_ATOMIC_LOAD_PTR(ep->me_value);
2309+
if (attr_o == NULL) {
23092310
POP_INPUT(dict);
23102311
DEOPT_IF(true);
23112312
}
2312-
attr_o = ep->me_value;
2313-
if (attr_o == NULL) {
2314-
UNLOCK_OBJECT(dict);
2313+
#ifdef Py_GIL_DISABLED
2314+
if (!_Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr)) {
23152315
POP_INPUT(dict);
23162316
DEOPT_IF(true);
23172317
}
2318-
STAT_INC(LOAD_ATTR, hit);
2318+
#else
23192319
attr = PyStackRef_FromPyObjectNew(attr_o);
2320-
UNLOCK_OBJECT(dict);
2320+
#endif
2321+
STAT_INC(LOAD_ATTR, hit);
23212322
DEAD(dict);
23222323
DECREF_INPUTS();
23232324
}

Python/executor_cases.c.h

+18-14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

+18-14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)