Skip to content

Commit 7d2d3b2

Browse files
authored
Merge branch 'main' into copy_module_frozendict
2 parents 8b877ac + d1b541b commit 7d2d3b2

File tree

2 files changed

+58
-7
lines changed

2 files changed

+58
-7
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Optimize :meth:`!frozendict.fromkeys` to avoid unnecessary thread-safety operations
2+
in frozendict cases. Patch by Donghee Na.

Objects/dictobject.c

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2671,10 +2671,8 @@ _PyDict_LoadBuiltinsFromGlobals(PyObject *globals)
26712671

26722672
/* Consumes references to key and value */
26732673
static int
2674-
setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value)
2674+
anydict_setitem_take2(PyDictObject *mp, PyObject *key, PyObject *value)
26752675
{
2676-
ASSERT_DICT_LOCKED(mp);
2677-
26782676
assert(key);
26792677
assert(value);
26802678
assert(PyAnyDict_Check(mp));
@@ -2693,6 +2691,14 @@ setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value)
26932691
return insertdict(mp, key, hash, value);
26942692
}
26952693

2694+
/* Consumes references to key and value */
2695+
static int
2696+
setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value)
2697+
{
2698+
ASSERT_DICT_LOCKED(mp);
2699+
return anydict_setitem_take2(mp, key, value);
2700+
}
2701+
26962702
int
26972703
_PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value)
26982704
{
@@ -3284,15 +3290,23 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
32843290
return NULL;
32853291

32863292

3287-
if (PyAnyDict_CheckExact(d)) {
3288-
if (PyAnyDict_CheckExact(iterable)) {
3293+
if (PyDict_CheckExact(d)) {
3294+
if (PyDict_CheckExact(iterable)) {
32893295
PyDictObject *mp = (PyDictObject *)d;
32903296

32913297
Py_BEGIN_CRITICAL_SECTION2(d, iterable);
32923298
d = (PyObject *)dict_dict_fromkeys(mp, iterable, value);
32933299
Py_END_CRITICAL_SECTION2();
32943300
return d;
32953301
}
3302+
else if (PyFrozenDict_CheckExact(iterable)) {
3303+
PyDictObject *mp = (PyDictObject *)d;
3304+
3305+
Py_BEGIN_CRITICAL_SECTION(d);
3306+
d = (PyObject *)dict_dict_fromkeys(mp, iterable, value);
3307+
Py_END_CRITICAL_SECTION();
3308+
return d;
3309+
}
32963310
else if (PyAnySet_CheckExact(iterable)) {
32973311
PyDictObject *mp = (PyDictObject *)d;
32983312

@@ -3302,14 +3316,37 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
33023316
return d;
33033317
}
33043318
}
3319+
else if (PyFrozenDict_CheckExact(d)) {
3320+
if (PyDict_CheckExact(iterable)) {
3321+
PyDictObject *mp = (PyDictObject *)d;
3322+
3323+
Py_BEGIN_CRITICAL_SECTION(iterable);
3324+
d = (PyObject *)dict_dict_fromkeys(mp, iterable, value);
3325+
Py_END_CRITICAL_SECTION();
3326+
return d;
3327+
}
3328+
else if (PyFrozenDict_CheckExact(iterable)) {
3329+
PyDictObject *mp = (PyDictObject *)d;
3330+
d = (PyObject *)dict_dict_fromkeys(mp, iterable, value);
3331+
return d;
3332+
}
3333+
else if (PyAnySet_CheckExact(iterable)) {
3334+
PyDictObject *mp = (PyDictObject *)d;
3335+
3336+
Py_BEGIN_CRITICAL_SECTION(iterable);
3337+
d = (PyObject *)dict_set_fromkeys(mp, iterable, value);
3338+
Py_END_CRITICAL_SECTION();
3339+
return d;
3340+
}
3341+
}
33053342

33063343
it = PyObject_GetIter(iterable);
33073344
if (it == NULL){
33083345
Py_DECREF(d);
33093346
return NULL;
33103347
}
33113348

3312-
if (PyAnyDict_CheckExact(d)) {
3349+
if (PyDict_CheckExact(d)) {
33133350
Py_BEGIN_CRITICAL_SECTION(d);
33143351
while ((key = PyIter_Next(it)) != NULL) {
33153352
status = setitem_lock_held((PyDictObject *)d, key, value);
@@ -3321,7 +3358,19 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
33213358
}
33223359
dict_iter_exit:;
33233360
Py_END_CRITICAL_SECTION();
3324-
} else {
3361+
}
3362+
else if (PyFrozenDict_CheckExact(d)) {
3363+
while ((key = PyIter_Next(it)) != NULL) {
3364+
// anydict_setitem_take2 consumes a reference to key
3365+
status = anydict_setitem_take2((PyDictObject *)d,
3366+
key, Py_NewRef(value));
3367+
if (status < 0) {
3368+
assert(PyErr_Occurred());
3369+
goto Fail;
3370+
}
3371+
}
3372+
}
3373+
else {
33253374
while ((key = PyIter_Next(it)) != NULL) {
33263375
status = PyObject_SetItem(d, key, value);
33273376
Py_DECREF(key);

0 commit comments

Comments
 (0)