Issue #28959: Added private macro PyDict_GET_SIZE for retrieving the size of dict.
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 67b163d..8d1eddc 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -2409,8 +2409,7 @@
     assert(nargs >= 0);
     assert(kwargs == NULL || PyDict_CheckExact(kwargs));
 
-    nkwargs = (kwargs != NULL) ? PyDict_Size(kwargs) : 0;
-    if (!nkwargs) {
+    if (kwargs == NULL || (nkwargs = PyDict_GET_SIZE(kwargs)) == 0) {
         *p_kwnames = NULL;
         return args;
     }
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 090c9cd..ed39891 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -1173,7 +1173,7 @@
         return (*wk)(self, args, wp->descr->d_wrapped, kwds);
     }
 
-    if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_Size(kwds) != 0)) {
+    if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) {
         PyErr_Format(PyExc_TypeError,
                      "wrapper %s doesn't take keyword arguments",
                      wp->descr->d_base->name);
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index 69cd973..63aa9de 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -583,7 +583,7 @@
 
     if (kw != NULL && PyDict_Check(kw)) {
         Py_ssize_t pos, i;
-        nk = PyDict_Size(kw);
+        nk = PyDict_GET_SIZE(kw);
         kwtuple = PyTuple_New(2*nk);
         if (kwtuple == NULL)
             return NULL;
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index c2001f0..14750b6 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -87,6 +87,7 @@
     Py_ssize_t size;
     int flags;
 
+    assert(kwds == NULL || PyDict_Check(kwds));
     /* PyCFunction_Call() must not be called with an exception set,
        because it may clear it (directly or indirectly) and so the
        caller loses its exception */
@@ -103,7 +104,7 @@
         res = _PyCFunction_FastCallDict(func, stack, nargs, kwds);
     }
     else {
-        if (kwds != NULL && PyDict_Size(kwds) != 0) {
+        if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
             PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
                          f->m_ml->ml_name);
             return NULL;
@@ -176,7 +177,7 @@
     switch (flags)
     {
     case METH_NOARGS:
-        if (kwargs != NULL && PyDict_Size(kwargs) != 0) {
+        if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
             PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
                          func->m_ml->ml_name);
             return NULL;
@@ -193,7 +194,7 @@
         break;
 
     case METH_O:
-        if (kwargs != NULL && PyDict_Size(kwargs) != 0) {
+        if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
             PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
                          func->m_ml->ml_name);
             return NULL;
@@ -215,7 +216,7 @@
         /* Slow-path: create a temporary tuple */
         PyObject *tuple;
 
-        if (!(flags & METH_KEYWORDS) && kwargs != NULL && PyDict_Size(kwargs) != 0) {
+        if (!(flags & METH_KEYWORDS) && kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
             PyErr_Format(PyExc_TypeError,
                          "%.200s() takes no keyword arguments",
                          func->m_ml->ml_name);
diff --git a/Objects/object.c b/Objects/object.c
index 9a7c7f7..dc50131 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1454,7 +1454,7 @@
 static PyObject *
 none_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
-    if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_Size(kwargs))) {
+    if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) {
         PyErr_SetString(PyExc_TypeError, "NoneType takes no arguments");
         return NULL;
     }
@@ -1573,7 +1573,7 @@
 static PyObject *
 notimplemented_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
-    if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_Size(kwargs))) {
+    if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) {
         PyErr_SetString(PyExc_TypeError, "NotImplementedType takes no arguments");
         return NULL;
     }
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
index 6b33386..8e6d643 100644
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -2423,8 +2423,7 @@
 
     /* now handle kwargs */
     assert(kwargs == NULL || PyDict_Check(kwargs));
-    len = (kwargs != NULL) ? PyDict_Size(kwargs) : 0;
-    if (len > 0) {
+    if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) {
         PyObject *items = PyDict_Items(kwargs);
         if (items == NULL)
             return NULL;
diff --git a/Objects/setobject.c b/Objects/setobject.c
index b7e0617..59ed795 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -981,7 +981,7 @@
         PyObject *value;
         Py_ssize_t pos = 0;
         Py_hash_t hash;
-        Py_ssize_t dictsize = PyDict_Size(other);
+        Py_ssize_t dictsize = PyDict_GET_SIZE(other);
 
         /* Do one big resize at the start, rather than
         * incrementally resizing as we insert new keys.  Expect
diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c
index 2f32355..1dc7e4e 100644
--- a/Objects/sliceobject.c
+++ b/Objects/sliceobject.c
@@ -19,7 +19,7 @@
 static PyObject *
 ellipsis_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
-    if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_Size(kwargs))) {
+    if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) {
         PyErr_SetString(PyExc_TypeError, "EllipsisType takes no arguments");
         return NULL;
     }
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 391eed3..37f0082 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -902,7 +902,7 @@
     if (type == &PyType_Type &&
         PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
         (kwds == NULL ||
-         (PyDict_Check(kwds) && PyDict_Size(kwds) == 0)))
+         (PyDict_Check(kwds) && PyDict_GET_SIZE(kwds) == 0)))
         return obj;
 
     /* If the returned object is not an instance of type,
@@ -1585,7 +1585,7 @@
             }
         }
     }
-    n = PyDict_Size(set);
+    n = PyDict_GET_SIZE(set);
 
     off = PyOS_snprintf(buf, sizeof(buf), "Cannot create a \
 consistent method resolution\norder (MRO) for bases");
@@ -2187,7 +2187,7 @@
     assert(kwds == NULL || PyDict_Check(kwds));
 
     if (kwds != NULL && PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
-        PyDict_Check(kwds) && PyDict_Size(kwds) != 0) {
+        PyDict_Check(kwds) && PyDict_GET_SIZE(kwds) != 0) {
         PyErr_SetString(PyExc_TypeError,
                         "type.__init__() takes no keyword arguments");
         return -1;
@@ -2272,7 +2272,7 @@
        Note: We don't call PyType_CheckExact as that also allows subclasses */
     if (metatype == &PyType_Type) {
         const Py_ssize_t nargs = PyTuple_GET_SIZE(args);
-        const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_Size(kwds);
+        const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_GET_SIZE(kwds);
 
         if (nargs == 1 && nkwds == 0) {
             PyObject *x = PyTuple_GET_ITEM(args, 0);
@@ -3416,7 +3416,7 @@
 excess_args(PyObject *args, PyObject *kwds)
 {
     return PyTuple_GET_SIZE(args) ||
-        (kwds && PyDict_Check(kwds) && PyDict_Size(kwds));
+        (kwds && PyDict_Check(kwds) && PyDict_GET_SIZE(kwds));
 }
 
 static int
@@ -3894,7 +3894,7 @@
                We also return None if the dict is empty to make the behavior
                consistent regardless whether the dict was initialized or not.
                This make unit testing easier. */
-            if (dict != NULL && *dict != NULL && PyDict_Size(*dict) > 0) {
+            if (dict != NULL && *dict != NULL && PyDict_GET_SIZE(*dict)) {
                 state = *dict;
             }
             else {
@@ -3983,7 +3983,7 @@
 
             /* If we found some slot attributes, pack them in a tuple along
                the original attribute dictionary. */
-            if (PyDict_Size(slots) > 0) {
+            if (PyDict_GET_SIZE(slots) > 0) {
                 PyObject *state2;
 
                 state2 = PyTuple_Pack(2, state, slots);
@@ -4175,7 +4175,7 @@
         return NULL;
     }
     hasargs = (args != NULL);
-    if (kwargs == NULL || PyDict_Size(kwargs) == 0) {
+    if (kwargs == NULL || PyDict_GET_SIZE(kwargs) == 0) {
         _Py_IDENTIFIER(__newobj__);
         PyObject *cls;
         Py_ssize_t i, n;