Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
19a70e7f
Kaydet (Commit)
19a70e7f
authored
Kas 13, 2015
tarafından
Serhiy Storchaka
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Issue #25462: The hash of the key now is calculated only once in most
operations in C implementation of OrderedDict.
üst
33be3e3d
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
86 additions
and
35 deletions
+86
-35
NEWS
Misc/NEWS
+3
-0
odictobject.c
Objects/odictobject.c
+83
-35
No files found.
Misc/NEWS
Dosyayı görüntüle @
19a70e7f
...
@@ -11,6 +11,9 @@ Release date: TBA
...
@@ -11,6 +11,9 @@ Release date: TBA
Core and Builtins
Core and Builtins
-----------------
-----------------
- Issue #25462: The hash of the key now is calculated only once in most
operations in C implementation of OrderedDict.
- Issue #22995: Default implementation of __reduce__ and __reduce_ex__ now
- Issue #22995: Default implementation of __reduce__ and __reduce_ex__ now
rejects builtin types with not defined __new__.
rejects builtin types with not defined __new__.
...
...
Objects/odictobject.c
Dosyayı görüntüle @
19a70e7f
...
@@ -88,15 +88,16 @@ For adding nodes:
...
@@ -88,15 +88,16 @@ For adding nodes:
* _odict_add_head(od, node)
* _odict_add_head(od, node)
* _odict_add_tail(od, node)
* _odict_add_tail(od, node)
* _odict_add_new_node(od, key)
* _odict_add_new_node(od, key
, hash
)
For removing nodes:
For removing nodes:
* _odict_clear_node(od, node)
* _odict_clear_node(od, node
, key, hash
)
* _odict_clear_nodes(od, clear_each)
* _odict_clear_nodes(od, clear_each)
Others:
Others:
* _odict_find_node_hash(od, key, hash)
* _odict_find_node(od, key)
* _odict_find_node(od, key)
* _odict_keys_equal(od1, od2)
* _odict_keys_equal(od1, od2)
...
@@ -532,7 +533,7 @@ _odict_free_fast_nodes(PyODictObject *od) {
...
@@ -532,7 +533,7 @@ _odict_free_fast_nodes(PyODictObject *od) {
/* Return the index into the hash table, regardless of a valid node. */
/* Return the index into the hash table, regardless of a valid node. */
static
Py_ssize_t
static
Py_ssize_t
_odict_get_index_
hash
(
PyODictObject
*
od
,
PyObject
*
key
,
Py_hash_t
hash
)
_odict_get_index_
raw
(
PyODictObject
*
od
,
PyObject
*
key
,
Py_hash_t
hash
)
{
{
PyObject
**
value_addr
=
NULL
;
PyObject
**
value_addr
=
NULL
;
PyDictKeyEntry
*
ep
;
PyDictKeyEntry
*
ep
;
...
@@ -563,7 +564,7 @@ _odict_resize(PyODictObject *od) {
...
@@ -563,7 +564,7 @@ _odict_resize(PyODictObject *od) {
/* Copy the current nodes into the table. */
/* Copy the current nodes into the table. */
_odict_FOREACH
(
od
,
node
)
{
_odict_FOREACH
(
od
,
node
)
{
i
=
_odict_get_index_
hash
(
od
,
_odictnode_KEY
(
node
),
i
=
_odict_get_index_
raw
(
od
,
_odictnode_KEY
(
node
),
_odictnode_HASH
(
node
));
_odictnode_HASH
(
node
));
if
(
i
<
0
)
{
if
(
i
<
0
)
{
PyMem_FREE
(
fast_nodes
);
PyMem_FREE
(
fast_nodes
);
...
@@ -582,15 +583,11 @@ _odict_resize(PyODictObject *od) {
...
@@ -582,15 +583,11 @@ _odict_resize(PyODictObject *od) {
/* Return the index into the hash table, regardless of a valid node. */
/* Return the index into the hash table, regardless of a valid node. */
static
Py_ssize_t
static
Py_ssize_t
_odict_get_index
(
PyODictObject
*
od
,
PyObject
*
key
)
_odict_get_index
(
PyODictObject
*
od
,
PyObject
*
key
,
Py_hash_t
hash
)
{
{
Py_hash_t
hash
;
PyDictKeysObject
*
keys
;
PyDictKeysObject
*
keys
;
assert
(
key
!=
NULL
);
assert
(
key
!=
NULL
);
hash
=
PyObject_Hash
(
key
);
if
(
hash
==
-
1
)
return
-
1
;
keys
=
((
PyDictObject
*
)
od
)
->
ma_keys
;
keys
=
((
PyDictObject
*
)
od
)
->
ma_keys
;
/* Ensure od_fast_nodes and dk_entries are in sync. */
/* Ensure od_fast_nodes and dk_entries are in sync. */
...
@@ -601,18 +598,35 @@ _odict_get_index(PyODictObject *od, PyObject *key)
...
@@ -601,18 +598,35 @@ _odict_get_index(PyODictObject *od, PyObject *key)
return
-
1
;
return
-
1
;
}
}
return
_odict_get_index_
hash
(
od
,
key
,
hash
);
return
_odict_get_index_
raw
(
od
,
key
,
hash
);
}
}
/* Returns NULL if there was some error or the key was not found. */
/* Returns NULL if there was some error or the key was not found. */
static
_ODictNode
*
_odict_find_node_hash
(
PyODictObject
*
od
,
PyObject
*
key
,
Py_hash_t
hash
)
{
Py_ssize_t
index
;
if
(
_odict_EMPTY
(
od
))
return
NULL
;
index
=
_odict_get_index
(
od
,
key
,
hash
);
if
(
index
<
0
)
return
NULL
;
return
od
->
od_fast_nodes
[
index
];
}
static
_ODictNode
*
static
_ODictNode
*
_odict_find_node
(
PyODictObject
*
od
,
PyObject
*
key
)
_odict_find_node
(
PyODictObject
*
od
,
PyObject
*
key
)
{
{
Py_ssize_t
index
;
Py_ssize_t
index
;
Py_hash_t
hash
;
if
(
_odict_EMPTY
(
od
))
if
(
_odict_EMPTY
(
od
))
return
NULL
;
return
NULL
;
index
=
_odict_get_index
(
od
,
key
);
hash
=
PyObject_Hash
(
key
);
if
(
hash
==
-
1
)
return
NULL
;
index
=
_odict_get_index
(
od
,
key
,
hash
);
if
(
index
<
0
)
if
(
index
<
0
)
return
NULL
;
return
NULL
;
return
od
->
od_fast_nodes
[
index
];
return
od
->
od_fast_nodes
[
index
];
...
@@ -646,18 +660,13 @@ _odict_add_tail(PyODictObject *od, _ODictNode *node)
...
@@ -646,18 +660,13 @@ _odict_add_tail(PyODictObject *od, _ODictNode *node)
/* adds the node to the end of the list */
/* adds the node to the end of the list */
static
int
static
int
_odict_add_new_node
(
PyODictObject
*
od
,
PyObject
*
key
)
_odict_add_new_node
(
PyODictObject
*
od
,
PyObject
*
key
,
Py_hash_t
hash
)
{
{
Py_hash_t
hash
;
Py_ssize_t
i
;
Py_ssize_t
i
;
_ODictNode
*
node
;
_ODictNode
*
node
;
hash
=
PyObject_Hash
(
key
);
if
(
hash
==
-
1
)
return
-
1
;
Py_INCREF
(
key
);
Py_INCREF
(
key
);
i
=
_odict_get_index
(
od
,
key
);
i
=
_odict_get_index
(
od
,
key
,
hash
);
if
(
i
<
0
)
{
if
(
i
<
0
)
{
if
(
!
PyErr_Occurred
())
if
(
!
PyErr_Occurred
())
PyErr_SetObject
(
PyExc_KeyError
,
key
);
PyErr_SetObject
(
PyExc_KeyError
,
key
);
...
@@ -728,7 +737,8 @@ _odict_remove_node(PyODictObject *od, _ODictNode *node)
...
@@ -728,7 +737,8 @@ _odict_remove_node(PyODictObject *od, _ODictNode *node)
we modify od_fast_nodes.
we modify od_fast_nodes.
*/
*/
static
int
static
int
_odict_clear_node
(
PyODictObject
*
od
,
_ODictNode
*
node
,
PyObject
*
key
)
_odict_clear_node
(
PyODictObject
*
od
,
_ODictNode
*
node
,
PyObject
*
key
,
Py_hash_t
hash
)
{
{
Py_ssize_t
i
;
Py_ssize_t
i
;
...
@@ -738,7 +748,7 @@ _odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key)
...
@@ -738,7 +748,7 @@ _odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key)
return
0
;
return
0
;
}
}
i
=
_odict_get_index
(
od
,
key
);
i
=
_odict_get_index
(
od
,
key
,
hash
);
if
(
i
<
0
)
if
(
i
<
0
)
return
PyErr_Occurred
()
?
-
1
:
0
;
return
PyErr_Occurred
()
?
-
1
:
0
;
...
@@ -1091,7 +1101,8 @@ odict_pop(PyObject *od, PyObject *args, PyObject *kwargs)
...
@@ -1091,7 +1101,8 @@ odict_pop(PyObject *od, PyObject *args, PyObject *kwargs)
}
}
static
PyObject
*
static
PyObject
*
_odict_popkey
(
PyObject
*
od
,
PyObject
*
key
,
PyObject
*
failobj
)
_odict_popkey_hash
(
PyObject
*
od
,
PyObject
*
key
,
PyObject
*
failobj
,
Py_hash_t
hash
)
{
{
_ODictNode
*
node
;
_ODictNode
*
node
;
PyObject
*
value
=
NULL
;
PyObject
*
value
=
NULL
;
...
@@ -1099,13 +1110,13 @@ _odict_popkey(PyObject *od, PyObject *key, PyObject *failobj)
...
@@ -1099,13 +1110,13 @@ _odict_popkey(PyObject *od, PyObject *key, PyObject *failobj)
/* Pop the node first to avoid a possible dict resize (due to
/* Pop the node first to avoid a possible dict resize (due to
eval loop reentrancy) and complications due to hash collision
eval loop reentrancy) and complications due to hash collision
resolution. */
resolution. */
node
=
_odict_find_node
((
PyODictObject
*
)
od
,
key
);
node
=
_odict_find_node
_hash
((
PyODictObject
*
)
od
,
key
,
hash
);
if
(
node
==
NULL
)
{
if
(
node
==
NULL
)
{
if
(
PyErr_Occurred
())
if
(
PyErr_Occurred
())
return
NULL
;
return
NULL
;
}
}
else
{
else
{
int
res
=
_odict_clear_node
((
PyODictObject
*
)
od
,
node
,
key
);
int
res
=
_odict_clear_node
((
PyODictObject
*
)
od
,
node
,
key
,
hash
);
if
(
res
<
0
)
{
if
(
res
<
0
)
{
return
NULL
;
return
NULL
;
}
}
...
@@ -1114,8 +1125,14 @@ _odict_popkey(PyObject *od, PyObject *key, PyObject *failobj)
...
@@ -1114,8 +1125,14 @@ _odict_popkey(PyObject *od, PyObject *key, PyObject *failobj)
/* Now delete the value from the dict. */
/* Now delete the value from the dict. */
if
(
PyODict_CheckExact
(
od
))
{
if
(
PyODict_CheckExact
(
od
))
{
if
(
node
!=
NULL
)
{
if
(
node
!=
NULL
)
{
/* We could do PyDict_GetItem() and PyDict_DelItem() directly... */
value
=
_PyDict_GetItem_KnownHash
(
od
,
key
,
hash
);
/* borrowed */
value
=
_PyDict_Pop
((
PyDictObject
*
)
od
,
key
,
failobj
);
if
(
value
!=
NULL
)
{
Py_INCREF
(
value
);
if
(
_PyDict_DelItem_KnownHash
(
od
,
key
,
hash
)
<
0
)
{
Py_DECREF
(
value
);
return
NULL
;
}
}
}
}
}
}
else
{
else
{
...
@@ -1146,6 +1163,16 @@ _odict_popkey(PyObject *od, PyObject *key, PyObject *failobj)
...
@@ -1146,6 +1163,16 @@ _odict_popkey(PyObject *od, PyObject *key, PyObject *failobj)
return
value
;
return
value
;
}
}
static
PyObject
*
_odict_popkey
(
PyObject
*
od
,
PyObject
*
key
,
PyObject
*
failobj
)
{
Py_hash_t
hash
=
PyObject_Hash
(
key
);
if
(
hash
==
-
1
)
return
NULL
;
return
_odict_popkey_hash
(
od
,
key
,
failobj
,
hash
);
}
/* popitem() */
/* popitem() */
PyDoc_STRVAR
(
odict_popitem__doc__
,
PyDoc_STRVAR
(
odict_popitem__doc__
,
...
@@ -1178,7 +1205,7 @@ odict_popitem(PyObject *od, PyObject *args, PyObject *kwargs)
...
@@ -1178,7 +1205,7 @@ odict_popitem(PyObject *od, PyObject *args, PyObject *kwargs)
node
=
last
?
_odict_LAST
(
od
)
:
_odict_FIRST
(
od
);
node
=
last
?
_odict_LAST
(
od
)
:
_odict_FIRST
(
od
);
key
=
_odictnode_KEY
(
node
);
key
=
_odictnode_KEY
(
node
);
Py_INCREF
(
key
);
Py_INCREF
(
key
);
value
=
_odict_popkey
(
od
,
key
,
NULL
);
value
=
_odict_popkey
_hash
(
od
,
key
,
NULL
,
_odictnode_HASH
(
node
)
);
if
(
value
==
NULL
)
if
(
value
==
NULL
)
return
NULL
;
return
NULL
;
item
=
PyTuple_Pack
(
2
,
key
,
value
);
item
=
PyTuple_Pack
(
2
,
key
,
value
);
...
@@ -1237,6 +1264,10 @@ odict_clear(register PyODictObject *od)
...
@@ -1237,6 +1264,10 @@ odict_clear(register PyODictObject *od)
/* copy() */
/* copy() */
/* forward */
static
int
_PyODict_SetItem_KnownHash
(
PyObject
*
,
PyObject
*
,
PyObject
*
,
Py_hash_t
);
PyDoc_STRVAR
(
odict_copy__doc__
,
"od.copy() -> a shallow copy of od"
);
PyDoc_STRVAR
(
odict_copy__doc__
,
"od.copy() -> a shallow copy of od"
);
static
PyObject
*
static
PyObject
*
...
@@ -1261,7 +1292,8 @@ odict_copy(register PyODictObject *od)
...
@@ -1261,7 +1292,8 @@ odict_copy(register PyODictObject *od)
PyErr_SetObject
(
PyExc_KeyError
,
key
);
PyErr_SetObject
(
PyExc_KeyError
,
key
);
goto
fail
;
goto
fail
;
}
}
if
(
PyODict_SetItem
((
PyObject
*
)
od_copy
,
key
,
value
)
!=
0
)
if
(
_PyODict_SetItem_KnownHash
((
PyObject
*
)
od_copy
,
key
,
value
,
_odictnode_HASH
(
node
))
!=
0
)
goto
fail
;
goto
fail
;
}
}
}
}
...
@@ -1720,16 +1752,18 @@ PyODict_New(void) {
...
@@ -1720,16 +1752,18 @@ PyODict_New(void) {
return
odict_new
(
&
PyODict_Type
,
NULL
,
NULL
);
return
odict_new
(
&
PyODict_Type
,
NULL
,
NULL
);
};
};
int
static
int
PyODict_SetItem
(
PyObject
*
od
,
PyObject
*
key
,
PyObject
*
value
)
{
_PyODict_SetItem_KnownHash
(
PyObject
*
od
,
PyObject
*
key
,
PyObject
*
value
,
int
res
=
PyDict_SetItem
(
od
,
key
,
value
);
Py_hash_t
hash
)
{
int
res
=
_PyDict_SetItem_KnownHash
(
od
,
key
,
value
,
hash
);
if
(
res
==
0
)
{
if
(
res
==
0
)
{
res
=
_odict_add_new_node
((
PyODictObject
*
)
od
,
key
);
res
=
_odict_add_new_node
((
PyODictObject
*
)
od
,
key
,
hash
);
if
(
res
<
0
)
{
if
(
res
<
0
)
{
/* Revert setting the value on the dict */
/* Revert setting the value on the dict */
PyObject
*
exc
,
*
val
,
*
tb
;
PyObject
*
exc
,
*
val
,
*
tb
;
PyErr_Fetch
(
&
exc
,
&
val
,
&
tb
);
PyErr_Fetch
(
&
exc
,
&
val
,
&
tb
);
(
void
)
PyDict_DelItem
(
od
,
key
);
(
void
)
_PyDict_DelItem_KnownHash
(
od
,
key
,
hash
);
_PyErr_ChainExceptions
(
exc
,
val
,
tb
);
_PyErr_ChainExceptions
(
exc
,
val
,
tb
);
}
}
}
}
...
@@ -1737,11 +1771,25 @@ PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value) {
...
@@ -1737,11 +1771,25 @@ PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value) {
};
};
int
int
PyODict_DelItem
(
PyObject
*
od
,
PyObject
*
key
)
{
PyODict_SetItem
(
PyObject
*
od
,
PyObject
*
key
,
PyObject
*
value
)
int
res
=
_odict_clear_node
((
PyODictObject
*
)
od
,
NULL
,
key
);
{
Py_hash_t
hash
=
PyObject_Hash
(
key
);
if
(
hash
==
-
1
)
return
-
1
;
return
_PyODict_SetItem_KnownHash
(
od
,
key
,
value
,
hash
);
};
int
PyODict_DelItem
(
PyObject
*
od
,
PyObject
*
key
)
{
int
res
;
Py_hash_t
hash
=
PyObject_Hash
(
key
);
if
(
hash
==
-
1
)
return
-
1
;
res
=
_odict_clear_node
((
PyODictObject
*
)
od
,
NULL
,
key
,
hash
);
if
(
res
<
0
)
if
(
res
<
0
)
return
-
1
;
return
-
1
;
return
PyDict_DelItem
(
od
,
key
);
return
_PyDict_DelItem_KnownHash
(
od
,
key
,
hash
);
};
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment