mirror of https://github.com/python/cpython
gh-99845: Change _PyDict_KeysSize() return type to size_t (#99848)
* Change _PyDict_KeysSize() and shared_keys_usable_size() return type from signed (Py_ssize_t) to unsigned (size_t) type. * new_values() argument type is now unsigned (size_t). * init_inline_values() now uses size_t rather than int for the 'i' iterator variable. * type.__sizeof__() implementation now uses unsigned (size_t) type.
This commit is contained in:
parent
4cfc1b8568
commit
4246fe977d
|
@ -39,7 +39,7 @@ extern PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *);
|
||||||
* Returns the version number, or zero if it was not possible to get a version number. */
|
* Returns the version number, or zero if it was not possible to get a version number. */
|
||||||
extern uint32_t _PyDictKeys_GetVersionForCurrentState(PyDictKeysObject *dictkeys);
|
extern uint32_t _PyDictKeys_GetVersionForCurrentState(PyDictKeysObject *dictkeys);
|
||||||
|
|
||||||
extern Py_ssize_t _PyDict_KeysSize(PyDictKeysObject *keys);
|
extern size_t _PyDict_KeysSize(PyDictKeysObject *keys);
|
||||||
|
|
||||||
/* _Py_dict_lookup() returns index of entry which can be used like DK_ENTRIES(dk)[index].
|
/* _Py_dict_lookup() returns index of entry which can be used like DK_ENTRIES(dk)[index].
|
||||||
* -1 when no entry found, -3 when compare raises error.
|
* -1 when no entry found, -3 when compare raises error.
|
||||||
|
|
|
@ -685,9 +685,9 @@ free_keys_object(PyDictKeysObject *keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline PyDictValues*
|
static inline PyDictValues*
|
||||||
new_values(Py_ssize_t size)
|
new_values(size_t size)
|
||||||
{
|
{
|
||||||
assert(size > 0);
|
assert(size >= 1);
|
||||||
size_t prefix_size = _Py_SIZE_ROUND_UP(size+2, sizeof(PyObject *));
|
size_t prefix_size = _Py_SIZE_ROUND_UP(size+2, sizeof(PyObject *));
|
||||||
assert(prefix_size < 256);
|
assert(prefix_size < 256);
|
||||||
size_t n = prefix_size + size * sizeof(PyObject *);
|
size_t n = prefix_size + size * sizeof(PyObject *);
|
||||||
|
@ -746,27 +746,24 @@ new_dict(PyDictKeysObject *keys, PyDictValues *values, Py_ssize_t used, int free
|
||||||
return (PyObject *)mp;
|
return (PyObject *)mp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Py_ssize_t
|
static inline size_t
|
||||||
shared_keys_usable_size(PyDictKeysObject *keys)
|
shared_keys_usable_size(PyDictKeysObject *keys)
|
||||||
{
|
{
|
||||||
return keys->dk_nentries + keys->dk_usable;
|
return (size_t)keys->dk_nentries + (size_t)keys->dk_usable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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(PyDictKeysObject *keys)
|
||||||
{
|
{
|
||||||
PyDictValues *values;
|
size_t size = shared_keys_usable_size(keys);
|
||||||
Py_ssize_t i, size;
|
PyDictValues *values = new_values(size);
|
||||||
|
|
||||||
size = shared_keys_usable_size(keys);
|
|
||||||
values = new_values(size);
|
|
||||||
if (values == NULL) {
|
if (values == NULL) {
|
||||||
dictkeys_decref(keys);
|
dictkeys_decref(keys);
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
}
|
}
|
||||||
((char *)values)[-2] = 0;
|
((char *)values)[-2] = 0;
|
||||||
for (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(keys, values, 0, 1);
|
||||||
|
@ -781,7 +778,7 @@ clone_combined_dict_keys(PyDictObject *orig)
|
||||||
assert(orig->ma_values == NULL);
|
assert(orig->ma_values == NULL);
|
||||||
assert(orig->ma_keys->dk_refcnt == 1);
|
assert(orig->ma_keys->dk_refcnt == 1);
|
||||||
|
|
||||||
Py_ssize_t keys_size = _PyDict_KeysSize(orig->ma_keys);
|
size_t keys_size = _PyDict_KeysSize(orig->ma_keys);
|
||||||
PyDictKeysObject *keys = PyObject_Malloc(keys_size);
|
PyDictKeysObject *keys = PyObject_Malloc(keys_size);
|
||||||
if (keys == NULL) {
|
if (keys == NULL) {
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
|
@ -2959,7 +2956,6 @@ PyDict_Copy(PyObject *o)
|
||||||
{
|
{
|
||||||
PyObject *copy;
|
PyObject *copy;
|
||||||
PyDictObject *mp;
|
PyDictObject *mp;
|
||||||
Py_ssize_t i, n;
|
|
||||||
|
|
||||||
if (o == NULL || !PyDict_Check(o)) {
|
if (o == NULL || !PyDict_Check(o)) {
|
||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
|
@ -2974,9 +2970,8 @@ PyDict_Copy(PyObject *o)
|
||||||
|
|
||||||
if (_PyDict_HasSplitTable(mp)) {
|
if (_PyDict_HasSplitTable(mp)) {
|
||||||
PyDictObject *split_copy;
|
PyDictObject *split_copy;
|
||||||
Py_ssize_t size = shared_keys_usable_size(mp->ma_keys);
|
size_t size = shared_keys_usable_size(mp->ma_keys);
|
||||||
PyDictValues *newvalues;
|
PyDictValues *newvalues = new_values(size);
|
||||||
newvalues = new_values(size);
|
|
||||||
if (newvalues == NULL)
|
if (newvalues == NULL)
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
split_copy = PyObject_GC_New(PyDictObject, &PyDict_Type);
|
split_copy = PyObject_GC_New(PyDictObject, &PyDict_Type);
|
||||||
|
@ -2991,7 +2986,7 @@ PyDict_Copy(PyObject *o)
|
||||||
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();
|
||||||
dictkeys_incref(mp->ma_keys);
|
dictkeys_incref(mp->ma_keys);
|
||||||
for (i = 0, n = size; i < n; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
PyObject *value = mp->ma_values->values[i];
|
PyObject *value = mp->ma_values->values[i];
|
||||||
split_copy->ma_values->values[i] = Py_XNewRef(value);
|
split_copy->ma_values->values[i] = Py_XNewRef(value);
|
||||||
}
|
}
|
||||||
|
@ -3514,9 +3509,7 @@ static PyObject *dictiter_new(PyDictObject *, PyTypeObject *);
|
||||||
Py_ssize_t
|
Py_ssize_t
|
||||||
_PyDict_SizeOf(PyDictObject *mp)
|
_PyDict_SizeOf(PyDictObject *mp)
|
||||||
{
|
{
|
||||||
Py_ssize_t res;
|
size_t res = _PyObject_SIZE(Py_TYPE(mp));
|
||||||
|
|
||||||
res = _PyObject_SIZE(Py_TYPE(mp));
|
|
||||||
if (mp->ma_values) {
|
if (mp->ma_values) {
|
||||||
res += shared_keys_usable_size(mp->ma_keys) * sizeof(PyObject*);
|
res += shared_keys_usable_size(mp->ma_keys) * sizeof(PyObject*);
|
||||||
}
|
}
|
||||||
|
@ -3525,17 +3518,19 @@ _PyDict_SizeOf(PyDictObject *mp)
|
||||||
if (mp->ma_keys->dk_refcnt == 1) {
|
if (mp->ma_keys->dk_refcnt == 1) {
|
||||||
res += _PyDict_KeysSize(mp->ma_keys);
|
res += _PyDict_KeysSize(mp->ma_keys);
|
||||||
}
|
}
|
||||||
return res;
|
assert(res <= (size_t)PY_SSIZE_T_MAX);
|
||||||
|
return (Py_ssize_t)res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_ssize_t
|
size_t
|
||||||
_PyDict_KeysSize(PyDictKeysObject *keys)
|
_PyDict_KeysSize(PyDictKeysObject *keys)
|
||||||
{
|
{
|
||||||
size_t es = keys->dk_kind == DICT_KEYS_GENERAL
|
size_t es = (keys->dk_kind == DICT_KEYS_GENERAL
|
||||||
? sizeof(PyDictKeyEntry) : sizeof(PyDictUnicodeEntry);
|
? sizeof(PyDictKeyEntry) : sizeof(PyDictUnicodeEntry));
|
||||||
return (sizeof(PyDictKeysObject)
|
size_t size = sizeof(PyDictKeysObject);
|
||||||
+ ((size_t)1 << keys->dk_log2_index_bytes)
|
size += (size_t)1 << keys->dk_log2_index_bytes;
|
||||||
+ USABLE_FRACTION(DK_SIZE(keys)) * es);
|
size += USABLE_FRACTION((size_t)DK_SIZE(keys)) * es;
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -5286,16 +5281,15 @@ init_inline_values(PyObject *obj, PyTypeObject *tp)
|
||||||
if (keys->dk_usable > 1) {
|
if (keys->dk_usable > 1) {
|
||||||
keys->dk_usable--;
|
keys->dk_usable--;
|
||||||
}
|
}
|
||||||
Py_ssize_t size = shared_keys_usable_size(keys);
|
size_t size = shared_keys_usable_size(keys);
|
||||||
assert(size > 0);
|
|
||||||
PyDictValues *values = new_values(size);
|
PyDictValues *values = new_values(size);
|
||||||
if (values == NULL) {
|
if (values == NULL) {
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
assert(((uint8_t *)values)[-1] >= size+2);
|
assert(((uint8_t *)values)[-1] >= (size + 2));
|
||||||
((uint8_t *)values)[-2] = 0;
|
((uint8_t *)values)[-2] = 0;
|
||||||
for (int i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
values->values[i] = NULL;
|
values->values[i] = NULL;
|
||||||
}
|
}
|
||||||
_PyDictOrValues_SetValues(_PyObject_DictOrValuesPointer(obj), values);
|
_PyDictOrValues_SetValues(_PyObject_DictOrValuesPointer(obj), values);
|
||||||
|
@ -5335,7 +5329,8 @@ make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values)
|
||||||
dictkeys_incref(keys);
|
dictkeys_incref(keys);
|
||||||
Py_ssize_t used = 0;
|
Py_ssize_t used = 0;
|
||||||
Py_ssize_t track = 0;
|
Py_ssize_t track = 0;
|
||||||
for (Py_ssize_t i = 0; i < shared_keys_usable_size(keys); i++) {
|
size_t size = shared_keys_usable_size(keys);
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
PyObject *val = values->values[i];
|
PyObject *val = values->values[i];
|
||||||
if (val != NULL) {
|
if (val != NULL) {
|
||||||
used += 1;
|
used += 1;
|
||||||
|
|
|
@ -4680,16 +4680,17 @@ static PyObject *
|
||||||
type___sizeof___impl(PyTypeObject *self)
|
type___sizeof___impl(PyTypeObject *self)
|
||||||
/*[clinic end generated code: output=766f4f16cd3b1854 input=99398f24b9cf45d6]*/
|
/*[clinic end generated code: output=766f4f16cd3b1854 input=99398f24b9cf45d6]*/
|
||||||
{
|
{
|
||||||
Py_ssize_t size;
|
size_t size;
|
||||||
if (self->tp_flags & Py_TPFLAGS_HEAPTYPE) {
|
if (self->tp_flags & Py_TPFLAGS_HEAPTYPE) {
|
||||||
PyHeapTypeObject* et = (PyHeapTypeObject*)self;
|
PyHeapTypeObject* et = (PyHeapTypeObject*)self;
|
||||||
size = sizeof(PyHeapTypeObject);
|
size = sizeof(PyHeapTypeObject);
|
||||||
if (et->ht_cached_keys)
|
if (et->ht_cached_keys)
|
||||||
size += _PyDict_KeysSize(et->ht_cached_keys);
|
size += _PyDict_KeysSize(et->ht_cached_keys);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
size = sizeof(PyTypeObject);
|
size = sizeof(PyTypeObject);
|
||||||
return PyLong_FromSsize_t(size);
|
}
|
||||||
|
return PyLong_FromSize_t(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef type_methods[] = {
|
static PyMethodDef type_methods[] = {
|
||||||
|
|
Loading…
Reference in New Issue