mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
gh-100227: Move dict_state.global_version to PyInterpreterState (gh-102338)
https://github.com/python/cpython/issues/100227
This commit is contained in:
parent
58d761e5b5
commit
b45d14b886
6 changed files with 160 additions and 109 deletions
|
@ -149,8 +149,8 @@ static inline PyDictUnicodeEntry* DK_UNICODE_ENTRIES(PyDictKeysObject *dk) {
|
||||||
#define DICT_VERSION_INCREMENT (1 << DICT_MAX_WATCHERS)
|
#define DICT_VERSION_INCREMENT (1 << DICT_MAX_WATCHERS)
|
||||||
#define DICT_VERSION_MASK (DICT_VERSION_INCREMENT - 1)
|
#define DICT_VERSION_MASK (DICT_VERSION_INCREMENT - 1)
|
||||||
|
|
||||||
#define DICT_NEXT_VERSION() \
|
#define DICT_NEXT_VERSION(INTERP) \
|
||||||
(_PyRuntime.dict_state.global_version += DICT_VERSION_INCREMENT)
|
((INTERP)->dict_state.global_version += DICT_VERSION_INCREMENT)
|
||||||
|
|
||||||
void
|
void
|
||||||
_PyDict_SendEvent(int watcher_bits,
|
_PyDict_SendEvent(int watcher_bits,
|
||||||
|
@ -160,7 +160,8 @@ _PyDict_SendEvent(int watcher_bits,
|
||||||
PyObject *value);
|
PyObject *value);
|
||||||
|
|
||||||
static inline uint64_t
|
static inline uint64_t
|
||||||
_PyDict_NotifyEvent(PyDict_WatchEvent event,
|
_PyDict_NotifyEvent(PyInterpreterState *interp,
|
||||||
|
PyDict_WatchEvent event,
|
||||||
PyDictObject *mp,
|
PyDictObject *mp,
|
||||||
PyObject *key,
|
PyObject *key,
|
||||||
PyObject *value)
|
PyObject *value)
|
||||||
|
@ -169,9 +170,9 @@ _PyDict_NotifyEvent(PyDict_WatchEvent event,
|
||||||
int watcher_bits = mp->ma_version_tag & DICT_VERSION_MASK;
|
int watcher_bits = mp->ma_version_tag & DICT_VERSION_MASK;
|
||||||
if (watcher_bits) {
|
if (watcher_bits) {
|
||||||
_PyDict_SendEvent(watcher_bits, event, mp, key, value);
|
_PyDict_SendEvent(watcher_bits, event, mp, key, value);
|
||||||
return DICT_NEXT_VERSION() | watcher_bits;
|
return DICT_NEXT_VERSION(interp) | watcher_bits;
|
||||||
}
|
}
|
||||||
return DICT_NEXT_VERSION();
|
return DICT_NEXT_VERSION(interp);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern PyObject *_PyObject_MakeDictFromInstanceAttributes(PyObject *obj, PyDictValues *values);
|
extern PyObject *_PyObject_MakeDictFromInstanceAttributes(PyObject *obj, PyDictValues *values);
|
||||||
|
|
|
@ -9,14 +9,6 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct _Py_dict_runtime_state {
|
|
||||||
/*Global counter used to set ma_version_tag field of dictionary.
|
|
||||||
* It is incremented each time that a dictionary is created and each
|
|
||||||
* time that a dictionary is modified. */
|
|
||||||
uint64_t global_version;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef WITH_FREELISTS
|
#ifndef WITH_FREELISTS
|
||||||
// without freelists
|
// without freelists
|
||||||
# define PyDict_MAXFREELIST 0
|
# define PyDict_MAXFREELIST 0
|
||||||
|
@ -29,6 +21,10 @@ struct _Py_dict_runtime_state {
|
||||||
#define DICT_MAX_WATCHERS 8
|
#define DICT_MAX_WATCHERS 8
|
||||||
|
|
||||||
struct _Py_dict_state {
|
struct _Py_dict_state {
|
||||||
|
/*Global counter used to set ma_version_tag field of dictionary.
|
||||||
|
* It is incremented each time that a dictionary is created and each
|
||||||
|
* time that a dictionary is modified. */
|
||||||
|
uint64_t global_version;
|
||||||
uint32_t next_keys_version;
|
uint32_t next_keys_version;
|
||||||
|
|
||||||
#if PyDict_MAXFREELIST > 0
|
#if PyDict_MAXFREELIST > 0
|
||||||
|
|
|
@ -10,7 +10,6 @@ extern "C" {
|
||||||
|
|
||||||
#include "pycore_atomic.h" /* _Py_atomic_address */
|
#include "pycore_atomic.h" /* _Py_atomic_address */
|
||||||
#include "pycore_ceval_state.h" // struct _ceval_runtime_state
|
#include "pycore_ceval_state.h" // struct _ceval_runtime_state
|
||||||
#include "pycore_dict_state.h" // struct _Py_dict_runtime_state
|
|
||||||
#include "pycore_floatobject.h" // struct _Py_float_runtime_state
|
#include "pycore_floatobject.h" // struct _Py_float_runtime_state
|
||||||
#include "pycore_faulthandler.h" // struct _faulthandler_runtime_state
|
#include "pycore_faulthandler.h" // struct _faulthandler_runtime_state
|
||||||
#include "pycore_global_objects.h" // struct _Py_global_objects
|
#include "pycore_global_objects.h" // struct _Py_global_objects
|
||||||
|
@ -153,7 +152,6 @@ typedef struct pyruntimestate {
|
||||||
|
|
||||||
struct _Py_float_runtime_state float_state;
|
struct _Py_float_runtime_state float_state;
|
||||||
struct _Py_unicode_runtime_state unicode_state;
|
struct _Py_unicode_runtime_state unicode_state;
|
||||||
struct _Py_dict_runtime_state dict_state;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
/* Used to set PyTypeObject.tp_version_tag */
|
/* Used to set PyTypeObject.tp_version_tag */
|
||||||
|
|
|
@ -232,7 +232,8 @@ equally good collision statistics, needed less code & used less memory.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int dictresize(PyDictObject *mp, uint8_t log_newsize, int unicode);
|
static int dictresize(PyInterpreterState *interp, PyDictObject *mp,
|
||||||
|
uint8_t log_newsize, int unicode);
|
||||||
|
|
||||||
static PyObject* dict_iter(PyDictObject *dict);
|
static PyObject* dict_iter(PyDictObject *dict);
|
||||||
|
|
||||||
|
@ -241,9 +242,8 @@ static PyObject* dict_iter(PyDictObject *dict);
|
||||||
|
|
||||||
#if PyDict_MAXFREELIST > 0
|
#if PyDict_MAXFREELIST > 0
|
||||||
static struct _Py_dict_state *
|
static struct _Py_dict_state *
|
||||||
get_dict_state(void)
|
get_dict_state(PyInterpreterState *interp)
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
|
||||||
return &interp->dict_state;
|
return &interp->dict_state;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -289,7 +289,8 @@ void
|
||||||
_PyDict_DebugMallocStats(FILE *out)
|
_PyDict_DebugMallocStats(FILE *out)
|
||||||
{
|
{
|
||||||
#if PyDict_MAXFREELIST > 0
|
#if PyDict_MAXFREELIST > 0
|
||||||
struct _Py_dict_state *state = get_dict_state();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
struct _Py_dict_state *state = get_dict_state(interp);
|
||||||
_PyDebugAllocatorStats(out, "free PyDictObject",
|
_PyDebugAllocatorStats(out, "free PyDictObject",
|
||||||
state->numfree, sizeof(PyDictObject));
|
state->numfree, sizeof(PyDictObject));
|
||||||
#endif
|
#endif
|
||||||
|
@ -297,7 +298,7 @@ _PyDict_DebugMallocStats(FILE *out)
|
||||||
|
|
||||||
#define DK_MASK(dk) (DK_SIZE(dk)-1)
|
#define DK_MASK(dk) (DK_SIZE(dk)-1)
|
||||||
|
|
||||||
static void free_keys_object(PyDictKeysObject *keys);
|
static void free_keys_object(PyInterpreterState *interp, PyDictKeysObject *keys);
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
dictkeys_incref(PyDictKeysObject *dk)
|
dictkeys_incref(PyDictKeysObject *dk)
|
||||||
|
@ -309,14 +310,14 @@ dictkeys_incref(PyDictKeysObject *dk)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
dictkeys_decref(PyDictKeysObject *dk)
|
dictkeys_decref(PyInterpreterState *interp, PyDictKeysObject *dk)
|
||||||
{
|
{
|
||||||
assert(dk->dk_refcnt > 0);
|
assert(dk->dk_refcnt > 0);
|
||||||
#ifdef Py_REF_DEBUG
|
#ifdef Py_REF_DEBUG
|
||||||
_Py_DecRefTotal();
|
_Py_DecRefTotal();
|
||||||
#endif
|
#endif
|
||||||
if (--dk->dk_refcnt == 0) {
|
if (--dk->dk_refcnt == 0) {
|
||||||
free_keys_object(dk);
|
free_keys_object(interp, dk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,7 +587,7 @@ _PyDict_CheckConsistency(PyObject *op, int check_content)
|
||||||
|
|
||||||
|
|
||||||
static PyDictKeysObject*
|
static PyDictKeysObject*
|
||||||
new_keys_object(uint8_t log2_size, bool unicode)
|
new_keys_object(PyInterpreterState *interp, uint8_t log2_size, bool unicode)
|
||||||
{
|
{
|
||||||
PyDictKeysObject *dk;
|
PyDictKeysObject *dk;
|
||||||
Py_ssize_t usable;
|
Py_ssize_t usable;
|
||||||
|
@ -612,7 +613,7 @@ new_keys_object(uint8_t log2_size, bool unicode)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PyDict_MAXFREELIST > 0
|
#if PyDict_MAXFREELIST > 0
|
||||||
struct _Py_dict_state *state = get_dict_state();
|
struct _Py_dict_state *state = get_dict_state(interp);
|
||||||
#ifdef Py_DEBUG
|
#ifdef Py_DEBUG
|
||||||
// new_keys_object() must not be called after _PyDict_Fini()
|
// new_keys_object() must not be called after _PyDict_Fini()
|
||||||
assert(state->keys_numfree != -1);
|
assert(state->keys_numfree != -1);
|
||||||
|
@ -648,7 +649,7 @@ new_keys_object(uint8_t log2_size, bool unicode)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
free_keys_object(PyDictKeysObject *keys)
|
free_keys_object(PyInterpreterState *interp, PyDictKeysObject *keys)
|
||||||
{
|
{
|
||||||
assert(keys != Py_EMPTY_KEYS);
|
assert(keys != Py_EMPTY_KEYS);
|
||||||
if (DK_IS_UNICODE(keys)) {
|
if (DK_IS_UNICODE(keys)) {
|
||||||
|
@ -668,7 +669,7 @@ free_keys_object(PyDictKeysObject *keys)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if PyDict_MAXFREELIST > 0
|
#if PyDict_MAXFREELIST > 0
|
||||||
struct _Py_dict_state *state = get_dict_state();
|
struct _Py_dict_state *state = get_dict_state(interp);
|
||||||
#ifdef Py_DEBUG
|
#ifdef Py_DEBUG
|
||||||
// free_keys_object() must not be called after _PyDict_Fini()
|
// free_keys_object() must not be called after _PyDict_Fini()
|
||||||
assert(state->keys_numfree != -1);
|
assert(state->keys_numfree != -1);
|
||||||
|
@ -709,12 +710,14 @@ free_values(PyDictValues *values)
|
||||||
|
|
||||||
/* Consumes a reference to the keys object */
|
/* Consumes a reference to the keys object */
|
||||||
static PyObject *
|
static PyObject *
|
||||||
new_dict(PyDictKeysObject *keys, PyDictValues *values, Py_ssize_t used, int free_values_on_failure)
|
new_dict(PyInterpreterState *interp,
|
||||||
|
PyDictKeysObject *keys, PyDictValues *values,
|
||||||
|
Py_ssize_t used, int free_values_on_failure)
|
||||||
{
|
{
|
||||||
PyDictObject *mp;
|
PyDictObject *mp;
|
||||||
assert(keys != NULL);
|
assert(keys != NULL);
|
||||||
#if PyDict_MAXFREELIST > 0
|
#if PyDict_MAXFREELIST > 0
|
||||||
struct _Py_dict_state *state = get_dict_state();
|
struct _Py_dict_state *state = get_dict_state(interp);
|
||||||
#ifdef Py_DEBUG
|
#ifdef Py_DEBUG
|
||||||
// new_dict() must not be called after _PyDict_Fini()
|
// new_dict() must not be called after _PyDict_Fini()
|
||||||
assert(state->numfree != -1);
|
assert(state->numfree != -1);
|
||||||
|
@ -731,7 +734,7 @@ new_dict(PyDictKeysObject *keys, PyDictValues *values, Py_ssize_t used, int free
|
||||||
{
|
{
|
||||||
mp = PyObject_GC_New(PyDictObject, &PyDict_Type);
|
mp = PyObject_GC_New(PyDictObject, &PyDict_Type);
|
||||||
if (mp == NULL) {
|
if (mp == NULL) {
|
||||||
dictkeys_decref(keys);
|
dictkeys_decref(interp, keys);
|
||||||
if (free_values_on_failure) {
|
if (free_values_on_failure) {
|
||||||
free_values(values);
|
free_values(values);
|
||||||
}
|
}
|
||||||
|
@ -741,7 +744,7 @@ new_dict(PyDictKeysObject *keys, PyDictValues *values, Py_ssize_t used, int free
|
||||||
mp->ma_keys = keys;
|
mp->ma_keys = keys;
|
||||||
mp->ma_values = values;
|
mp->ma_values = values;
|
||||||
mp->ma_used = used;
|
mp->ma_used = used;
|
||||||
mp->ma_version_tag = DICT_NEXT_VERSION();
|
mp->ma_version_tag = DICT_NEXT_VERSION(interp);
|
||||||
ASSERT_CONSISTENT(mp);
|
ASSERT_CONSISTENT(mp);
|
||||||
return (PyObject *)mp;
|
return (PyObject *)mp;
|
||||||
}
|
}
|
||||||
|
@ -754,19 +757,19 @@ shared_keys_usable_size(PyDictKeysObject *keys)
|
||||||
|
|
||||||
/* Consumes a reference to the keys object */
|
/* Consumes a reference to the keys object */
|
||||||
static PyObject *
|
static PyObject *
|
||||||
new_dict_with_shared_keys(PyDictKeysObject *keys)
|
new_dict_with_shared_keys(PyInterpreterState *interp, PyDictKeysObject *keys)
|
||||||
{
|
{
|
||||||
size_t size = shared_keys_usable_size(keys);
|
size_t size = shared_keys_usable_size(keys);
|
||||||
PyDictValues *values = new_values(size);
|
PyDictValues *values = new_values(size);
|
||||||
if (values == NULL) {
|
if (values == NULL) {
|
||||||
dictkeys_decref(keys);
|
dictkeys_decref(interp, keys);
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
}
|
}
|
||||||
((char *)values)[-2] = 0;
|
((char *)values)[-2] = 0;
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
values->values[i] = NULL;
|
values->values[i] = NULL;
|
||||||
}
|
}
|
||||||
return new_dict(keys, values, 0, 1);
|
return new_dict(interp, keys, values, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -829,8 +832,9 @@ clone_combined_dict_keys(PyDictObject *orig)
|
||||||
PyObject *
|
PyObject *
|
||||||
PyDict_New(void)
|
PyDict_New(void)
|
||||||
{
|
{
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
dictkeys_incref(Py_EMPTY_KEYS);
|
dictkeys_incref(Py_EMPTY_KEYS);
|
||||||
return new_dict(Py_EMPTY_KEYS, NULL, 0, 0);
|
return new_dict(interp, Py_EMPTY_KEYS, NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search index of hash table from offset of entry table */
|
/* Search index of hash table from offset of entry table */
|
||||||
|
@ -1170,9 +1174,9 @@ find_empty_slot(PyDictKeysObject *keys, Py_hash_t hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
insertion_resize(PyDictObject *mp, int unicode)
|
insertion_resize(PyInterpreterState *interp, PyDictObject *mp, int unicode)
|
||||||
{
|
{
|
||||||
return dictresize(mp, calculate_log2_keysize(GROWTH_RATE(mp)), unicode);
|
return dictresize(interp, mp, calculate_log2_keysize(GROWTH_RATE(mp)), unicode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Py_ssize_t
|
static Py_ssize_t
|
||||||
|
@ -1214,12 +1218,13 @@ Returns -1 if an error occurred, or 0 on success.
|
||||||
Consumes key and value references.
|
Consumes key and value references.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
|
insertdict(PyInterpreterState *interp, PyDictObject *mp,
|
||||||
|
PyObject *key, Py_hash_t hash, PyObject *value)
|
||||||
{
|
{
|
||||||
PyObject *old_value;
|
PyObject *old_value;
|
||||||
|
|
||||||
if (DK_IS_UNICODE(mp->ma_keys) && !PyUnicode_CheckExact(key)) {
|
if (DK_IS_UNICODE(mp->ma_keys) && !PyUnicode_CheckExact(key)) {
|
||||||
if (insertion_resize(mp, 0) < 0)
|
if (insertion_resize(interp, mp, 0) < 0)
|
||||||
goto Fail;
|
goto Fail;
|
||||||
assert(mp->ma_keys->dk_kind == DICT_KEYS_GENERAL);
|
assert(mp->ma_keys->dk_kind == DICT_KEYS_GENERAL);
|
||||||
}
|
}
|
||||||
|
@ -1231,13 +1236,14 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
|
||||||
MAINTAIN_TRACKING(mp, key, value);
|
MAINTAIN_TRACKING(mp, key, value);
|
||||||
|
|
||||||
if (ix == DKIX_EMPTY) {
|
if (ix == DKIX_EMPTY) {
|
||||||
uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_ADDED, mp, key, value);
|
uint64_t new_version = _PyDict_NotifyEvent(
|
||||||
|
interp, PyDict_EVENT_ADDED, mp, key, value);
|
||||||
/* Insert into new slot. */
|
/* Insert into new slot. */
|
||||||
mp->ma_keys->dk_version = 0;
|
mp->ma_keys->dk_version = 0;
|
||||||
assert(old_value == NULL);
|
assert(old_value == NULL);
|
||||||
if (mp->ma_keys->dk_usable <= 0) {
|
if (mp->ma_keys->dk_usable <= 0) {
|
||||||
/* Need to resize. */
|
/* Need to resize. */
|
||||||
if (insertion_resize(mp, 1) < 0)
|
if (insertion_resize(interp, mp, 1) < 0)
|
||||||
goto Fail;
|
goto Fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1275,7 +1281,8 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (old_value != value) {
|
if (old_value != value) {
|
||||||
uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_MODIFIED, mp, key, value);
|
uint64_t new_version = _PyDict_NotifyEvent(
|
||||||
|
interp, PyDict_EVENT_MODIFIED, mp, key, value);
|
||||||
if (_PyDict_HasSplitTable(mp)) {
|
if (_PyDict_HasSplitTable(mp)) {
|
||||||
mp->ma_values->values[ix] = value;
|
mp->ma_values->values[ix] = value;
|
||||||
if (old_value == NULL) {
|
if (old_value == NULL) {
|
||||||
|
@ -1308,21 +1315,23 @@ Fail:
|
||||||
// Same to insertdict but specialized for ma_keys = Py_EMPTY_KEYS.
|
// Same to insertdict but specialized for ma_keys = Py_EMPTY_KEYS.
|
||||||
// Consumes key and value references.
|
// Consumes key and value references.
|
||||||
static int
|
static int
|
||||||
insert_to_emptydict(PyDictObject *mp, PyObject *key, Py_hash_t hash,
|
insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
|
||||||
PyObject *value)
|
PyObject *key, Py_hash_t hash, PyObject *value)
|
||||||
{
|
{
|
||||||
assert(mp->ma_keys == Py_EMPTY_KEYS);
|
assert(mp->ma_keys == Py_EMPTY_KEYS);
|
||||||
|
|
||||||
uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_ADDED, mp, key, value);
|
uint64_t new_version = _PyDict_NotifyEvent(
|
||||||
|
interp, PyDict_EVENT_ADDED, mp, key, value);
|
||||||
|
|
||||||
int unicode = PyUnicode_CheckExact(key);
|
int unicode = PyUnicode_CheckExact(key);
|
||||||
PyDictKeysObject *newkeys = new_keys_object(PyDict_LOG_MINSIZE, unicode);
|
PyDictKeysObject *newkeys = new_keys_object(
|
||||||
|
interp, PyDict_LOG_MINSIZE, unicode);
|
||||||
if (newkeys == NULL) {
|
if (newkeys == NULL) {
|
||||||
Py_DECREF(key);
|
Py_DECREF(key);
|
||||||
Py_DECREF(value);
|
Py_DECREF(value);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
dictkeys_decref(Py_EMPTY_KEYS);
|
dictkeys_decref(interp, Py_EMPTY_KEYS);
|
||||||
mp->ma_keys = newkeys;
|
mp->ma_keys = newkeys;
|
||||||
mp->ma_values = NULL;
|
mp->ma_values = NULL;
|
||||||
|
|
||||||
|
@ -1397,7 +1406,8 @@ This function supports:
|
||||||
- Generic -> Generic
|
- Generic -> Generic
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode)
|
dictresize(PyInterpreterState *interp, PyDictObject *mp,
|
||||||
|
uint8_t log2_newsize, int unicode)
|
||||||
{
|
{
|
||||||
PyDictKeysObject *oldkeys;
|
PyDictKeysObject *oldkeys;
|
||||||
PyDictValues *oldvalues;
|
PyDictValues *oldvalues;
|
||||||
|
@ -1421,7 +1431,7 @@ dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Allocate a new table. */
|
/* Allocate a new table. */
|
||||||
mp->ma_keys = new_keys_object(log2_newsize, unicode);
|
mp->ma_keys = new_keys_object(interp, log2_newsize, unicode);
|
||||||
if (mp->ma_keys == NULL) {
|
if (mp->ma_keys == NULL) {
|
||||||
mp->ma_keys = oldkeys;
|
mp->ma_keys = oldkeys;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1462,7 +1472,7 @@ dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode)
|
||||||
}
|
}
|
||||||
build_indices_unicode(mp->ma_keys, newentries, numentries);
|
build_indices_unicode(mp->ma_keys, newentries, numentries);
|
||||||
}
|
}
|
||||||
dictkeys_decref(oldkeys);
|
dictkeys_decref(interp, oldkeys);
|
||||||
mp->ma_values = NULL;
|
mp->ma_values = NULL;
|
||||||
free_values(oldvalues);
|
free_values(oldvalues);
|
||||||
}
|
}
|
||||||
|
@ -1530,7 +1540,7 @@ dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode)
|
||||||
assert(oldkeys->dk_kind != DICT_KEYS_SPLIT);
|
assert(oldkeys->dk_kind != DICT_KEYS_SPLIT);
|
||||||
assert(oldkeys->dk_refcnt == 1);
|
assert(oldkeys->dk_refcnt == 1);
|
||||||
#if PyDict_MAXFREELIST > 0
|
#if PyDict_MAXFREELIST > 0
|
||||||
struct _Py_dict_state *state = get_dict_state();
|
struct _Py_dict_state *state = get_dict_state(interp);
|
||||||
#ifdef Py_DEBUG
|
#ifdef Py_DEBUG
|
||||||
// dictresize() must not be called after _PyDict_Fini()
|
// dictresize() must not be called after _PyDict_Fini()
|
||||||
assert(state->keys_numfree != -1);
|
assert(state->keys_numfree != -1);
|
||||||
|
@ -1557,7 +1567,7 @@ dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
dict_new_presized(Py_ssize_t minused, bool unicode)
|
dict_new_presized(PyInterpreterState *interp, Py_ssize_t minused, bool unicode)
|
||||||
{
|
{
|
||||||
const uint8_t log2_max_presize = 17;
|
const uint8_t log2_max_presize = 17;
|
||||||
const Py_ssize_t max_presize = ((Py_ssize_t)1) << log2_max_presize;
|
const Py_ssize_t max_presize = ((Py_ssize_t)1) << log2_max_presize;
|
||||||
|
@ -1578,16 +1588,17 @@ dict_new_presized(Py_ssize_t minused, bool unicode)
|
||||||
log2_newsize = estimate_log2_keysize(minused);
|
log2_newsize = estimate_log2_keysize(minused);
|
||||||
}
|
}
|
||||||
|
|
||||||
new_keys = new_keys_object(log2_newsize, unicode);
|
new_keys = new_keys_object(interp, log2_newsize, unicode);
|
||||||
if (new_keys == NULL)
|
if (new_keys == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return new_dict(new_keys, NULL, 0, 0);
|
return new_dict(interp, new_keys, NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyDict_NewPresized(Py_ssize_t minused)
|
_PyDict_NewPresized(Py_ssize_t minused)
|
||||||
{
|
{
|
||||||
return dict_new_presized(minused, false);
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
return dict_new_presized(interp, minused, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
|
@ -1597,6 +1608,7 @@ _PyDict_FromItems(PyObject *const *keys, Py_ssize_t keys_offset,
|
||||||
{
|
{
|
||||||
bool unicode = true;
|
bool unicode = true;
|
||||||
PyObject *const *ks = keys;
|
PyObject *const *ks = keys;
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
|
||||||
for (Py_ssize_t i = 0; i < length; i++) {
|
for (Py_ssize_t i = 0; i < length; i++) {
|
||||||
if (!PyUnicode_CheckExact(*ks)) {
|
if (!PyUnicode_CheckExact(*ks)) {
|
||||||
|
@ -1606,7 +1618,7 @@ _PyDict_FromItems(PyObject *const *keys, Py_ssize_t keys_offset,
|
||||||
ks += keys_offset;
|
ks += keys_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *dict = dict_new_presized(length, unicode);
|
PyObject *dict = dict_new_presized(interp, length, unicode);
|
||||||
if (dict == NULL) {
|
if (dict == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1834,11 +1846,12 @@ _PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
if (mp->ma_keys == Py_EMPTY_KEYS) {
|
if (mp->ma_keys == Py_EMPTY_KEYS) {
|
||||||
return insert_to_emptydict(mp, key, hash, value);
|
return insert_to_emptydict(interp, mp, key, hash, value);
|
||||||
}
|
}
|
||||||
/* insertdict() handles any resizing that might be necessary */
|
/* insertdict() handles any resizing that might be necessary */
|
||||||
return insertdict(mp, key, hash, value);
|
return insertdict(interp, mp, key, hash, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CAUTION: PyDict_SetItem() must guarantee that it won't resize the
|
/* CAUTION: PyDict_SetItem() must guarantee that it won't resize the
|
||||||
|
@ -1875,11 +1888,12 @@ _PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value,
|
||||||
assert(hash != -1);
|
assert(hash != -1);
|
||||||
mp = (PyDictObject *)op;
|
mp = (PyDictObject *)op;
|
||||||
|
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
if (mp->ma_keys == Py_EMPTY_KEYS) {
|
if (mp->ma_keys == Py_EMPTY_KEYS) {
|
||||||
return insert_to_emptydict(mp, Py_NewRef(key), hash, Py_NewRef(value));
|
return insert_to_emptydict(interp, mp, Py_NewRef(key), hash, Py_NewRef(value));
|
||||||
}
|
}
|
||||||
/* insertdict() handles any resizing that might be necessary */
|
/* insertdict() handles any resizing that might be necessary */
|
||||||
return insertdict(mp, Py_NewRef(key), hash, Py_NewRef(value));
|
return insertdict(interp, mp, Py_NewRef(key), hash, Py_NewRef(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1977,7 +1991,9 @@ _PyDict_DelItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_DELETED, mp, key, NULL);
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
uint64_t new_version = _PyDict_NotifyEvent(
|
||||||
|
interp, PyDict_EVENT_DELETED, mp, key, NULL);
|
||||||
return delitem_common(mp, hash, ix, old_value, new_version);
|
return delitem_common(mp, hash, ix, old_value, new_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2020,7 +2036,9 @@ _PyDict_DelItemIf(PyObject *op, PyObject *key,
|
||||||
assert(hashpos >= 0);
|
assert(hashpos >= 0);
|
||||||
|
|
||||||
if (res > 0) {
|
if (res > 0) {
|
||||||
uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_DELETED, mp, key, NULL);
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
uint64_t new_version = _PyDict_NotifyEvent(
|
||||||
|
interp, PyDict_EVENT_DELETED, mp, key, NULL);
|
||||||
return delitem_common(mp, hashpos, ix, old_value, new_version);
|
return delitem_common(mp, hashpos, ix, old_value, new_version);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2045,7 +2063,9 @@ PyDict_Clear(PyObject *op)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Empty the dict... */
|
/* Empty the dict... */
|
||||||
uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_CLEARED, mp, NULL, NULL);
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
uint64_t new_version = _PyDict_NotifyEvent(
|
||||||
|
interp, PyDict_EVENT_CLEARED, mp, NULL, NULL);
|
||||||
dictkeys_incref(Py_EMPTY_KEYS);
|
dictkeys_incref(Py_EMPTY_KEYS);
|
||||||
mp->ma_keys = Py_EMPTY_KEYS;
|
mp->ma_keys = Py_EMPTY_KEYS;
|
||||||
mp->ma_values = NULL;
|
mp->ma_values = NULL;
|
||||||
|
@ -2057,11 +2077,11 @@ PyDict_Clear(PyObject *op)
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
Py_CLEAR(oldvalues->values[i]);
|
Py_CLEAR(oldvalues->values[i]);
|
||||||
free_values(oldvalues);
|
free_values(oldvalues);
|
||||||
dictkeys_decref(oldkeys);
|
dictkeys_decref(interp, oldkeys);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert(oldkeys->dk_refcnt == 1);
|
assert(oldkeys->dk_refcnt == 1);
|
||||||
dictkeys_decref(oldkeys);
|
dictkeys_decref(interp, oldkeys);
|
||||||
}
|
}
|
||||||
ASSERT_CONSISTENT(mp);
|
ASSERT_CONSISTENT(mp);
|
||||||
}
|
}
|
||||||
|
@ -2165,6 +2185,7 @@ _PyDict_Pop_KnownHash(PyObject *dict, PyObject *key, Py_hash_t hash, PyObject *d
|
||||||
Py_ssize_t ix;
|
Py_ssize_t ix;
|
||||||
PyObject *old_value;
|
PyObject *old_value;
|
||||||
PyDictObject *mp;
|
PyDictObject *mp;
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
|
||||||
assert(PyDict_Check(dict));
|
assert(PyDict_Check(dict));
|
||||||
mp = (PyDictObject *)dict;
|
mp = (PyDictObject *)dict;
|
||||||
|
@ -2187,7 +2208,8 @@ _PyDict_Pop_KnownHash(PyObject *dict, PyObject *key, Py_hash_t hash, PyObject *d
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
assert(old_value != NULL);
|
assert(old_value != NULL);
|
||||||
uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_DELETED, mp, key, NULL);
|
uint64_t new_version = _PyDict_NotifyEvent(
|
||||||
|
interp, PyDict_EVENT_DELETED, mp, key, NULL);
|
||||||
delitem_common(mp, hash, ix, Py_NewRef(old_value), new_version);
|
delitem_common(mp, hash, ix, Py_NewRef(old_value), new_version);
|
||||||
|
|
||||||
ASSERT_CONSISTENT(mp);
|
ASSERT_CONSISTENT(mp);
|
||||||
|
@ -2222,6 +2244,7 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
|
||||||
PyObject *key;
|
PyObject *key;
|
||||||
PyObject *d;
|
PyObject *d;
|
||||||
int status;
|
int status;
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
|
||||||
d = _PyObject_CallNoArgs(cls);
|
d = _PyObject_CallNoArgs(cls);
|
||||||
if (d == NULL)
|
if (d == NULL)
|
||||||
|
@ -2236,13 +2259,16 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
|
||||||
Py_hash_t hash;
|
Py_hash_t hash;
|
||||||
|
|
||||||
int unicode = DK_IS_UNICODE(((PyDictObject*)iterable)->ma_keys);
|
int unicode = DK_IS_UNICODE(((PyDictObject*)iterable)->ma_keys);
|
||||||
if (dictresize(mp, estimate_log2_keysize(PyDict_GET_SIZE(iterable)), unicode)) {
|
if (dictresize(interp, mp,
|
||||||
|
estimate_log2_keysize(PyDict_GET_SIZE(iterable)),
|
||||||
|
unicode)) {
|
||||||
Py_DECREF(d);
|
Py_DECREF(d);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (_PyDict_Next(iterable, &pos, &key, &oldvalue, &hash)) {
|
while (_PyDict_Next(iterable, &pos, &key, &oldvalue, &hash)) {
|
||||||
if (insertdict(mp, Py_NewRef(key), hash, Py_NewRef(value))) {
|
if (insertdict(interp, mp,
|
||||||
|
Py_NewRef(key), hash, Py_NewRef(value))) {
|
||||||
Py_DECREF(d);
|
Py_DECREF(d);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2255,13 +2281,14 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
|
||||||
PyObject *key;
|
PyObject *key;
|
||||||
Py_hash_t hash;
|
Py_hash_t hash;
|
||||||
|
|
||||||
if (dictresize(mp, estimate_log2_keysize(PySet_GET_SIZE(iterable)), 0)) {
|
if (dictresize(interp, mp,
|
||||||
|
estimate_log2_keysize(PySet_GET_SIZE(iterable)), 0)) {
|
||||||
Py_DECREF(d);
|
Py_DECREF(d);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (_PySet_NextEntry(iterable, &pos, &key, &hash)) {
|
while (_PySet_NextEntry(iterable, &pos, &key, &hash)) {
|
||||||
if (insertdict(mp, Py_NewRef(key), hash, Py_NewRef(value))) {
|
if (insertdict(interp, mp, Py_NewRef(key), hash, Py_NewRef(value))) {
|
||||||
Py_DECREF(d);
|
Py_DECREF(d);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2308,9 +2335,10 @@ Fail:
|
||||||
static void
|
static void
|
||||||
dict_dealloc(PyDictObject *mp)
|
dict_dealloc(PyDictObject *mp)
|
||||||
{
|
{
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
assert(Py_REFCNT(mp) == 0);
|
assert(Py_REFCNT(mp) == 0);
|
||||||
Py_SET_REFCNT(mp, 1);
|
Py_SET_REFCNT(mp, 1);
|
||||||
_PyDict_NotifyEvent(PyDict_EVENT_DEALLOCATED, mp, NULL, NULL);
|
_PyDict_NotifyEvent(interp, PyDict_EVENT_DEALLOCATED, mp, NULL, NULL);
|
||||||
if (Py_REFCNT(mp) > 1) {
|
if (Py_REFCNT(mp) > 1) {
|
||||||
Py_SET_REFCNT(mp, Py_REFCNT(mp) - 1);
|
Py_SET_REFCNT(mp, Py_REFCNT(mp) - 1);
|
||||||
return;
|
return;
|
||||||
|
@ -2328,14 +2356,14 @@ dict_dealloc(PyDictObject *mp)
|
||||||
Py_XDECREF(values->values[i]);
|
Py_XDECREF(values->values[i]);
|
||||||
}
|
}
|
||||||
free_values(values);
|
free_values(values);
|
||||||
dictkeys_decref(keys);
|
dictkeys_decref(interp, keys);
|
||||||
}
|
}
|
||||||
else if (keys != NULL) {
|
else if (keys != NULL) {
|
||||||
assert(keys->dk_refcnt == 1 || keys == Py_EMPTY_KEYS);
|
assert(keys->dk_refcnt == 1 || keys == Py_EMPTY_KEYS);
|
||||||
dictkeys_decref(keys);
|
dictkeys_decref(interp, keys);
|
||||||
}
|
}
|
||||||
#if PyDict_MAXFREELIST > 0
|
#if PyDict_MAXFREELIST > 0
|
||||||
struct _Py_dict_state *state = get_dict_state();
|
struct _Py_dict_state *state = get_dict_state(interp);
|
||||||
#ifdef Py_DEBUG
|
#ifdef Py_DEBUG
|
||||||
// new_dict() must not be called after _PyDict_Fini()
|
// new_dict() must not be called after _PyDict_Fini()
|
||||||
assert(state->numfree != -1);
|
assert(state->numfree != -1);
|
||||||
|
@ -2765,7 +2793,7 @@ Return:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dict_merge(PyObject *a, PyObject *b, int override)
|
dict_merge(PyInterpreterState *interp, PyObject *a, PyObject *b, int override)
|
||||||
{
|
{
|
||||||
PyDictObject *mp, *other;
|
PyDictObject *mp, *other;
|
||||||
|
|
||||||
|
@ -2799,13 +2827,14 @@ dict_merge(PyObject *a, PyObject *b, int override)
|
||||||
other->ma_used == okeys->dk_nentries &&
|
other->ma_used == okeys->dk_nentries &&
|
||||||
(DK_LOG_SIZE(okeys) == PyDict_LOG_MINSIZE ||
|
(DK_LOG_SIZE(okeys) == PyDict_LOG_MINSIZE ||
|
||||||
USABLE_FRACTION(DK_SIZE(okeys)/2) < other->ma_used)) {
|
USABLE_FRACTION(DK_SIZE(okeys)/2) < other->ma_used)) {
|
||||||
uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_CLONED, mp, b, NULL);
|
uint64_t new_version = _PyDict_NotifyEvent(
|
||||||
|
interp, PyDict_EVENT_CLONED, mp, b, NULL);
|
||||||
PyDictKeysObject *keys = clone_combined_dict_keys(other);
|
PyDictKeysObject *keys = clone_combined_dict_keys(other);
|
||||||
if (keys == NULL) {
|
if (keys == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dictkeys_decref(mp->ma_keys);
|
dictkeys_decref(interp, mp->ma_keys);
|
||||||
mp->ma_keys = keys;
|
mp->ma_keys = keys;
|
||||||
if (mp->ma_values != NULL) {
|
if (mp->ma_values != NULL) {
|
||||||
free_values(mp->ma_values);
|
free_values(mp->ma_values);
|
||||||
|
@ -2830,7 +2859,9 @@ dict_merge(PyObject *a, PyObject *b, int override)
|
||||||
*/
|
*/
|
||||||
if (USABLE_FRACTION(DK_SIZE(mp->ma_keys)) < other->ma_used) {
|
if (USABLE_FRACTION(DK_SIZE(mp->ma_keys)) < other->ma_used) {
|
||||||
int unicode = DK_IS_UNICODE(other->ma_keys);
|
int unicode = DK_IS_UNICODE(other->ma_keys);
|
||||||
if (dictresize(mp, estimate_log2_keysize(mp->ma_used + other->ma_used), unicode)) {
|
if (dictresize(interp, mp,
|
||||||
|
estimate_log2_keysize(mp->ma_used + other->ma_used),
|
||||||
|
unicode)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2845,12 +2876,14 @@ dict_merge(PyObject *a, PyObject *b, int override)
|
||||||
Py_INCREF(key);
|
Py_INCREF(key);
|
||||||
Py_INCREF(value);
|
Py_INCREF(value);
|
||||||
if (override == 1) {
|
if (override == 1) {
|
||||||
err = insertdict(mp, Py_NewRef(key), hash, Py_NewRef(value));
|
err = insertdict(interp, mp,
|
||||||
|
Py_NewRef(key), hash, Py_NewRef(value));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
err = _PyDict_Contains_KnownHash(a, key, hash);
|
err = _PyDict_Contains_KnownHash(a, key, hash);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
err = insertdict(mp, Py_NewRef(key), hash, Py_NewRef(value));
|
err = insertdict(interp, mp,
|
||||||
|
Py_NewRef(key), hash, Py_NewRef(value));
|
||||||
}
|
}
|
||||||
else if (err > 0) {
|
else if (err > 0) {
|
||||||
if (override != 0) {
|
if (override != 0) {
|
||||||
|
@ -2936,20 +2969,23 @@ dict_merge(PyObject *a, PyObject *b, int override)
|
||||||
int
|
int
|
||||||
PyDict_Update(PyObject *a, PyObject *b)
|
PyDict_Update(PyObject *a, PyObject *b)
|
||||||
{
|
{
|
||||||
return dict_merge(a, b, 1);
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
return dict_merge(interp, a, b, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
PyDict_Merge(PyObject *a, PyObject *b, int override)
|
PyDict_Merge(PyObject *a, PyObject *b, int override)
|
||||||
{
|
{
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
/* XXX Deprecate override not in (0, 1). */
|
/* XXX Deprecate override not in (0, 1). */
|
||||||
return dict_merge(a, b, override != 0);
|
return dict_merge(interp, a, b, override != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyDict_MergeEx(PyObject *a, PyObject *b, int override)
|
_PyDict_MergeEx(PyObject *a, PyObject *b, int override)
|
||||||
{
|
{
|
||||||
return dict_merge(a, b, override);
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
return dict_merge(interp, a, b, override);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -2963,6 +2999,7 @@ PyDict_Copy(PyObject *o)
|
||||||
{
|
{
|
||||||
PyObject *copy;
|
PyObject *copy;
|
||||||
PyDictObject *mp;
|
PyDictObject *mp;
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
|
||||||
if (o == NULL || !PyDict_Check(o)) {
|
if (o == NULL || !PyDict_Check(o)) {
|
||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
|
@ -2991,7 +3028,7 @@ PyDict_Copy(PyObject *o)
|
||||||
split_copy->ma_values = newvalues;
|
split_copy->ma_values = newvalues;
|
||||||
split_copy->ma_keys = mp->ma_keys;
|
split_copy->ma_keys = mp->ma_keys;
|
||||||
split_copy->ma_used = mp->ma_used;
|
split_copy->ma_used = mp->ma_used;
|
||||||
split_copy->ma_version_tag = DICT_NEXT_VERSION();
|
split_copy->ma_version_tag = DICT_NEXT_VERSION(interp);
|
||||||
dictkeys_incref(mp->ma_keys);
|
dictkeys_incref(mp->ma_keys);
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
PyObject *value = mp->ma_values->values[i];
|
PyObject *value = mp->ma_values->values[i];
|
||||||
|
@ -3024,7 +3061,7 @@ PyDict_Copy(PyObject *o)
|
||||||
if (keys == NULL) {
|
if (keys == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyDictObject *new = (PyDictObject *)new_dict(keys, NULL, 0, 0);
|
PyDictObject *new = (PyDictObject *)new_dict(interp, keys, NULL, 0, 0);
|
||||||
if (new == NULL) {
|
if (new == NULL) {
|
||||||
/* In case of an error, `new_dict()` takes care of
|
/* In case of an error, `new_dict()` takes care of
|
||||||
cleaning up `keys`. */
|
cleaning up `keys`. */
|
||||||
|
@ -3044,7 +3081,7 @@ PyDict_Copy(PyObject *o)
|
||||||
copy = PyDict_New();
|
copy = PyDict_New();
|
||||||
if (copy == NULL)
|
if (copy == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (dict_merge(copy, o, 1) == 0)
|
if (dict_merge(interp, copy, o, 1) == 0)
|
||||||
return copy;
|
return copy;
|
||||||
Py_DECREF(copy);
|
Py_DECREF(copy);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -3244,6 +3281,7 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
|
||||||
PyDictObject *mp = (PyDictObject *)d;
|
PyDictObject *mp = (PyDictObject *)d;
|
||||||
PyObject *value;
|
PyObject *value;
|
||||||
Py_hash_t hash;
|
Py_hash_t hash;
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
|
||||||
if (!PyDict_Check(d)) {
|
if (!PyDict_Check(d)) {
|
||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
|
@ -3257,7 +3295,7 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mp->ma_keys == Py_EMPTY_KEYS) {
|
if (mp->ma_keys == Py_EMPTY_KEYS) {
|
||||||
if (insert_to_emptydict(mp, Py_NewRef(key), hash,
|
if (insert_to_emptydict(interp, mp, Py_NewRef(key), hash,
|
||||||
Py_NewRef(defaultobj)) < 0) {
|
Py_NewRef(defaultobj)) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -3265,7 +3303,7 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PyUnicode_CheckExact(key) && DK_IS_UNICODE(mp->ma_keys)) {
|
if (!PyUnicode_CheckExact(key) && DK_IS_UNICODE(mp->ma_keys)) {
|
||||||
if (insertion_resize(mp, 0) < 0) {
|
if (insertion_resize(interp, mp, 0) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3275,11 +3313,12 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (ix == DKIX_EMPTY) {
|
if (ix == DKIX_EMPTY) {
|
||||||
uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_ADDED, mp, key, defaultobj);
|
uint64_t new_version = _PyDict_NotifyEvent(
|
||||||
|
interp, PyDict_EVENT_ADDED, mp, key, defaultobj);
|
||||||
mp->ma_keys->dk_version = 0;
|
mp->ma_keys->dk_version = 0;
|
||||||
value = defaultobj;
|
value = defaultobj;
|
||||||
if (mp->ma_keys->dk_usable <= 0) {
|
if (mp->ma_keys->dk_usable <= 0) {
|
||||||
if (insertion_resize(mp, 1) < 0) {
|
if (insertion_resize(interp, mp, 1) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3314,7 +3353,8 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
|
||||||
assert(mp->ma_keys->dk_usable >= 0);
|
assert(mp->ma_keys->dk_usable >= 0);
|
||||||
}
|
}
|
||||||
else if (value == NULL) {
|
else if (value == NULL) {
|
||||||
uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_ADDED, mp, key, defaultobj);
|
uint64_t new_version = _PyDict_NotifyEvent(
|
||||||
|
interp, PyDict_EVENT_ADDED, mp, key, defaultobj);
|
||||||
value = defaultobj;
|
value = defaultobj;
|
||||||
assert(_PyDict_HasSplitTable(mp));
|
assert(_PyDict_HasSplitTable(mp));
|
||||||
assert(mp->ma_values->values[ix] == NULL);
|
assert(mp->ma_values->values[ix] == NULL);
|
||||||
|
@ -3395,6 +3435,7 @@ dict_popitem_impl(PyDictObject *self)
|
||||||
Py_ssize_t i, j;
|
Py_ssize_t i, j;
|
||||||
PyObject *res;
|
PyObject *res;
|
||||||
uint64_t new_version;
|
uint64_t new_version;
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
|
||||||
/* Allocate the result tuple before checking the size. Believe it
|
/* Allocate the result tuple before checking the size. Believe it
|
||||||
* or not, this allocation could trigger a garbage collection which
|
* or not, this allocation could trigger a garbage collection which
|
||||||
|
@ -3415,7 +3456,7 @@ dict_popitem_impl(PyDictObject *self)
|
||||||
}
|
}
|
||||||
/* Convert split table to combined table */
|
/* Convert split table to combined table */
|
||||||
if (self->ma_keys->dk_kind == DICT_KEYS_SPLIT) {
|
if (self->ma_keys->dk_kind == DICT_KEYS_SPLIT) {
|
||||||
if (dictresize(self, DK_LOG_SIZE(self->ma_keys), 1)) {
|
if (dictresize(interp, self, DK_LOG_SIZE(self->ma_keys), 1)) {
|
||||||
Py_DECREF(res);
|
Py_DECREF(res);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -3434,7 +3475,8 @@ dict_popitem_impl(PyDictObject *self)
|
||||||
assert(i >= 0);
|
assert(i >= 0);
|
||||||
|
|
||||||
key = ep0[i].me_key;
|
key = ep0[i].me_key;
|
||||||
new_version = _PyDict_NotifyEvent(PyDict_EVENT_DELETED, self, key, NULL);
|
new_version = _PyDict_NotifyEvent(
|
||||||
|
interp, PyDict_EVENT_DELETED, self, key, NULL);
|
||||||
hash = unicode_get_hash(key);
|
hash = unicode_get_hash(key);
|
||||||
value = ep0[i].me_value;
|
value = ep0[i].me_value;
|
||||||
ep0[i].me_key = NULL;
|
ep0[i].me_key = NULL;
|
||||||
|
@ -3449,7 +3491,8 @@ dict_popitem_impl(PyDictObject *self)
|
||||||
assert(i >= 0);
|
assert(i >= 0);
|
||||||
|
|
||||||
key = ep0[i].me_key;
|
key = ep0[i].me_key;
|
||||||
new_version = _PyDict_NotifyEvent(PyDict_EVENT_DELETED, self, key, NULL);
|
new_version = _PyDict_NotifyEvent(
|
||||||
|
interp, PyDict_EVENT_DELETED, self, key, NULL);
|
||||||
hash = ep0[i].me_hash;
|
hash = ep0[i].me_hash;
|
||||||
value = ep0[i].me_value;
|
value = ep0[i].me_value;
|
||||||
ep0[i].me_key = NULL;
|
ep0[i].me_key = NULL;
|
||||||
|
@ -3708,7 +3751,8 @@ dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
PyDictObject *d = (PyDictObject *)self;
|
PyDictObject *d = (PyDictObject *)self;
|
||||||
|
|
||||||
d->ma_used = 0;
|
d->ma_used = 0;
|
||||||
d->ma_version_tag = DICT_NEXT_VERSION();
|
d->ma_version_tag = DICT_NEXT_VERSION(
|
||||||
|
_PyInterpreterState_GET());
|
||||||
dictkeys_incref(Py_EMPTY_KEYS);
|
dictkeys_incref(Py_EMPTY_KEYS);
|
||||||
d->ma_keys = Py_EMPTY_KEYS;
|
d->ma_keys = Py_EMPTY_KEYS;
|
||||||
d->ma_values = NULL;
|
d->ma_values = NULL;
|
||||||
|
@ -5262,7 +5306,9 @@ dictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
|
||||||
PyDictKeysObject *
|
PyDictKeysObject *
|
||||||
_PyDict_NewKeysForClass(void)
|
_PyDict_NewKeysForClass(void)
|
||||||
{
|
{
|
||||||
PyDictKeysObject *keys = new_keys_object(NEXT_LOG2_SHARED_KEYS_MAX_SIZE, 1);
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
PyDictKeysObject *keys = new_keys_object(
|
||||||
|
interp, NEXT_LOG2_SHARED_KEYS_MAX_SIZE, 1);
|
||||||
if (keys == NULL) {
|
if (keys == NULL) {
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
}
|
}
|
||||||
|
@ -5306,6 +5352,7 @@ init_inline_values(PyObject *obj, PyTypeObject *tp)
|
||||||
int
|
int
|
||||||
_PyObject_InitializeDict(PyObject *obj)
|
_PyObject_InitializeDict(PyObject *obj)
|
||||||
{
|
{
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
PyTypeObject *tp = Py_TYPE(obj);
|
PyTypeObject *tp = Py_TYPE(obj);
|
||||||
if (tp->tp_dictoffset == 0) {
|
if (tp->tp_dictoffset == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -5317,7 +5364,7 @@ _PyObject_InitializeDict(PyObject *obj)
|
||||||
PyObject *dict;
|
PyObject *dict;
|
||||||
if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) {
|
if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) {
|
||||||
dictkeys_incref(CACHED_KEYS(tp));
|
dictkeys_incref(CACHED_KEYS(tp));
|
||||||
dict = new_dict_with_shared_keys(CACHED_KEYS(tp));
|
dict = new_dict_with_shared_keys(interp, CACHED_KEYS(tp));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dict = PyDict_New();
|
dict = PyDict_New();
|
||||||
|
@ -5331,7 +5378,8 @@ _PyObject_InitializeDict(PyObject *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values)
|
make_dict_from_instance_attributes(PyInterpreterState *interp,
|
||||||
|
PyDictKeysObject *keys, PyDictValues *values)
|
||||||
{
|
{
|
||||||
dictkeys_incref(keys);
|
dictkeys_incref(keys);
|
||||||
Py_ssize_t used = 0;
|
Py_ssize_t used = 0;
|
||||||
|
@ -5344,7 +5392,7 @@ make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values)
|
||||||
track += _PyObject_GC_MAY_BE_TRACKED(val);
|
track += _PyObject_GC_MAY_BE_TRACKED(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PyObject *res = new_dict(keys, values, used, 0);
|
PyObject *res = new_dict(interp, keys, values, used, 0);
|
||||||
if (track && res) {
|
if (track && res) {
|
||||||
_PyObject_GC_TRACK(res);
|
_PyObject_GC_TRACK(res);
|
||||||
}
|
}
|
||||||
|
@ -5354,15 +5402,17 @@ make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values)
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyObject_MakeDictFromInstanceAttributes(PyObject *obj, PyDictValues *values)
|
_PyObject_MakeDictFromInstanceAttributes(PyObject *obj, PyDictValues *values)
|
||||||
{
|
{
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
|
PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
|
||||||
OBJECT_STAT_INC(dict_materialized_on_request);
|
OBJECT_STAT_INC(dict_materialized_on_request);
|
||||||
return make_dict_from_instance_attributes(keys, values);
|
return make_dict_from_instance_attributes(interp, keys, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
|
_PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
|
||||||
PyObject *name, PyObject *value)
|
PyObject *name, PyObject *value)
|
||||||
{
|
{
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
|
PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
|
||||||
assert(keys != NULL);
|
assert(keys != NULL);
|
||||||
assert(values != NULL);
|
assert(values != NULL);
|
||||||
|
@ -5385,7 +5435,8 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
|
||||||
OBJECT_STAT_INC(dict_materialized_str_subclass);
|
OBJECT_STAT_INC(dict_materialized_str_subclass);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
PyObject *dict = make_dict_from_instance_attributes(keys, values);
|
PyObject *dict = make_dict_from_instance_attributes(
|
||||||
|
interp, keys, values);
|
||||||
if (dict == NULL) {
|
if (dict == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -5564,13 +5615,15 @@ PyObject *
|
||||||
PyObject_GenericGetDict(PyObject *obj, void *context)
|
PyObject_GenericGetDict(PyObject *obj, void *context)
|
||||||
{
|
{
|
||||||
PyObject *dict;
|
PyObject *dict;
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
PyTypeObject *tp = Py_TYPE(obj);
|
PyTypeObject *tp = Py_TYPE(obj);
|
||||||
if (_PyType_HasFeature(tp, Py_TPFLAGS_MANAGED_DICT)) {
|
if (_PyType_HasFeature(tp, Py_TPFLAGS_MANAGED_DICT)) {
|
||||||
PyDictOrValues *dorv_ptr = _PyObject_DictOrValuesPointer(obj);
|
PyDictOrValues *dorv_ptr = _PyObject_DictOrValuesPointer(obj);
|
||||||
if (_PyDictOrValues_IsValues(*dorv_ptr)) {
|
if (_PyDictOrValues_IsValues(*dorv_ptr)) {
|
||||||
PyDictValues *values = _PyDictOrValues_GetValues(*dorv_ptr);
|
PyDictValues *values = _PyDictOrValues_GetValues(*dorv_ptr);
|
||||||
OBJECT_STAT_INC(dict_materialized_on_request);
|
OBJECT_STAT_INC(dict_materialized_on_request);
|
||||||
dict = make_dict_from_instance_attributes(CACHED_KEYS(tp), values);
|
dict = make_dict_from_instance_attributes(
|
||||||
|
interp, CACHED_KEYS(tp), values);
|
||||||
if (dict != NULL) {
|
if (dict != NULL) {
|
||||||
dorv_ptr->dict = dict;
|
dorv_ptr->dict = dict;
|
||||||
}
|
}
|
||||||
|
@ -5579,7 +5632,7 @@ PyObject_GenericGetDict(PyObject *obj, void *context)
|
||||||
dict = _PyDictOrValues_GetDict(*dorv_ptr);
|
dict = _PyDictOrValues_GetDict(*dorv_ptr);
|
||||||
if (dict == NULL) {
|
if (dict == NULL) {
|
||||||
dictkeys_incref(CACHED_KEYS(tp));
|
dictkeys_incref(CACHED_KEYS(tp));
|
||||||
dict = new_dict_with_shared_keys(CACHED_KEYS(tp));
|
dict = new_dict_with_shared_keys(interp, CACHED_KEYS(tp));
|
||||||
dorv_ptr->dict = dict;
|
dorv_ptr->dict = dict;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5596,7 +5649,8 @@ PyObject_GenericGetDict(PyObject *obj, void *context)
|
||||||
PyTypeObject *tp = Py_TYPE(obj);
|
PyTypeObject *tp = Py_TYPE(obj);
|
||||||
if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) {
|
if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) {
|
||||||
dictkeys_incref(CACHED_KEYS(tp));
|
dictkeys_incref(CACHED_KEYS(tp));
|
||||||
*dictptr = dict = new_dict_with_shared_keys(CACHED_KEYS(tp));
|
*dictptr = dict = new_dict_with_shared_keys(
|
||||||
|
interp, CACHED_KEYS(tp));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*dictptr = dict = PyDict_New();
|
*dictptr = dict = PyDict_New();
|
||||||
|
@ -5613,6 +5667,7 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
|
||||||
PyObject *dict;
|
PyObject *dict;
|
||||||
int res;
|
int res;
|
||||||
PyDictKeysObject *cached;
|
PyDictKeysObject *cached;
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
|
||||||
assert(dictptr != NULL);
|
assert(dictptr != NULL);
|
||||||
if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && (cached = CACHED_KEYS(tp))) {
|
if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && (cached = CACHED_KEYS(tp))) {
|
||||||
|
@ -5620,7 +5675,7 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
|
||||||
dict = *dictptr;
|
dict = *dictptr;
|
||||||
if (dict == NULL) {
|
if (dict == NULL) {
|
||||||
dictkeys_incref(cached);
|
dictkeys_incref(cached);
|
||||||
dict = new_dict_with_shared_keys(cached);
|
dict = new_dict_with_shared_keys(interp, cached);
|
||||||
if (dict == NULL)
|
if (dict == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
*dictptr = dict;
|
*dictptr = dict;
|
||||||
|
@ -5652,7 +5707,8 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
|
||||||
void
|
void
|
||||||
_PyDictKeys_DecRef(PyDictKeysObject *keys)
|
_PyDictKeys_DecRef(PyDictKeysObject *keys)
|
||||||
{
|
{
|
||||||
dictkeys_decref(keys);
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
dictkeys_decref(interp, keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t _PyDictKeys_GetVersionForCurrentState(PyInterpreterState *interp,
|
uint32_t _PyDictKeys_GetVersionForCurrentState(PyInterpreterState *interp,
|
||||||
|
|
|
@ -1679,7 +1679,7 @@ dummy_func(
|
||||||
DEOPT_IF(ep->me_key != name, STORE_ATTR);
|
DEOPT_IF(ep->me_key != name, STORE_ATTR);
|
||||||
old_value = ep->me_value;
|
old_value = ep->me_value;
|
||||||
DEOPT_IF(old_value == NULL, STORE_ATTR);
|
DEOPT_IF(old_value == NULL, STORE_ATTR);
|
||||||
new_version = _PyDict_NotifyEvent(PyDict_EVENT_MODIFIED, dict, name, value);
|
new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);
|
||||||
ep->me_value = value;
|
ep->me_value = value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1687,7 +1687,7 @@ dummy_func(
|
||||||
DEOPT_IF(ep->me_key != name, STORE_ATTR);
|
DEOPT_IF(ep->me_key != name, STORE_ATTR);
|
||||||
old_value = ep->me_value;
|
old_value = ep->me_value;
|
||||||
DEOPT_IF(old_value == NULL, STORE_ATTR);
|
DEOPT_IF(old_value == NULL, STORE_ATTR);
|
||||||
new_version = _PyDict_NotifyEvent(PyDict_EVENT_MODIFIED, dict, name, value);
|
new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);
|
||||||
ep->me_value = value;
|
ep->me_value = value;
|
||||||
}
|
}
|
||||||
Py_DECREF(old_value);
|
Py_DECREF(old_value);
|
||||||
|
|
4
Python/generated_cases.c.h
generated
4
Python/generated_cases.c.h
generated
|
@ -2114,7 +2114,7 @@
|
||||||
DEOPT_IF(ep->me_key != name, STORE_ATTR);
|
DEOPT_IF(ep->me_key != name, STORE_ATTR);
|
||||||
old_value = ep->me_value;
|
old_value = ep->me_value;
|
||||||
DEOPT_IF(old_value == NULL, STORE_ATTR);
|
DEOPT_IF(old_value == NULL, STORE_ATTR);
|
||||||
new_version = _PyDict_NotifyEvent(PyDict_EVENT_MODIFIED, dict, name, value);
|
new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);
|
||||||
ep->me_value = value;
|
ep->me_value = value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2122,7 +2122,7 @@
|
||||||
DEOPT_IF(ep->me_key != name, STORE_ATTR);
|
DEOPT_IF(ep->me_key != name, STORE_ATTR);
|
||||||
old_value = ep->me_value;
|
old_value = ep->me_value;
|
||||||
DEOPT_IF(old_value == NULL, STORE_ATTR);
|
DEOPT_IF(old_value == NULL, STORE_ATTR);
|
||||||
new_version = _PyDict_NotifyEvent(PyDict_EVENT_MODIFIED, dict, name, value);
|
new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);
|
||||||
ep->me_value = value;
|
ep->me_value = value;
|
||||||
}
|
}
|
||||||
Py_DECREF(old_value);
|
Py_DECREF(old_value);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue