diff --git a/PORT_STATUS.md b/PORT_STATUS.md index 725ef2f..2ba7493 100644 --- a/PORT_STATUS.md +++ b/PORT_STATUS.md @@ -1,4 +1,29 @@ -## Latest revision (`dict_keys()` C89 declarations hoisted; frontier advances in dictobject.c) +## Latest revision (frameobject C89 work; frontier advances past floatobject) + +Date: 2026-10-02 19:09 UTC + +The CPython checkout remains at baseline tag `v3.11.16`, commit `41388c9cb160d0886d5ca00d2e6c878260a8a4549`. Preserved the existing outer and detached CPython working trees; no reset, clean, stash, or discard. Regenerated `compat/msvc600/cpython-3.11.16-vc6-headers.patch` from the complete nested CPython diff and verified byte-for-byte. The outer Gitea commit will contain that patch, focused tests, and this status log; the nested checkout remains detached/uncommitted. + +Continued the C89 port after a fresh forced VC6 probe found `Objects/exceptions.c` at 84/85. Exception-group and exception metadata declarations were hoisted in earlier edits; subsequent forced probes compiled past exceptions, fileobject, and floatobject. In this continuation: + +- `Objects/fileobject.c`: hoisted `Py_OpenCodeHookFunction hook` in `PyFile_OpenCodeObject()` while leaving lookup after path validation. +- `Objects/clinic/floatobject.c.h` and `Objects/floatobject.c`: moved the `typestr_length` declaration; corrected C89 declarations in float packing, exact deallocation, `PyFloat_AsDouble`, vectorcall, and format detection; replaced the designated `PyFloat_Type.tp_vectorcall` initializer with positional trailing slots; replaced `1ULL`-style concern in frame stack threshold via `PY_ULL(1)`. +- `Objects/frameobject.c`: corrected `frame_getlocals`, stack-swap helpers, overflow literal, stack analysis (`mark_stacks`), incompatible-stack lookup, line marking, and loop-local declarations. Execution/ownership order was retained in the focused checked paths. + +Focused regressions pass: + +- `python3 scripts/vc6-fileobject-opencode-c89.test.py cpython/Objects/fileobject.c` +- `python3 scripts/vc6-floatobject-pack4-c89.test.py cpython/Objects/floatobject.c cpython/Objects/clinic/floatobject.c.h` +- `python3 scripts/vc6-frameobject-c89.test.py cpython/Objects/frameobject.c` +- `git -C cpython diff --check` + +The latest forced probe compiled **87/88** translation units and moved the first blocker to `Objects/frameobject.c`. First diagnostics are C2275/C2146/C2065 for late `PyFrameState state` in `frame_setlineno()` at line 686; further diagnostics in that function and later frameobject code are follow-on C89 issues. Full log: `build/current-recheck/frontier-frame-current.log`. Next step is test-first declaration hoisting in `frame_setlineno()`, preserving validation/cleanup order, then re-probe. + +This is compile-frontier evidence only. No interpreter has been linked or runtime-tested under Wine or Windows 98 SE. No commit or push has yet been made for this continuation. + +--- + +## Previous revision (fresh frontier recheck; floatobject declarations already fixed) Date: 2026-10-02 16:22 UTC diff --git a/compat/msvc600/cpython-3.11.16-vc6-headers.patch b/compat/msvc600/cpython-3.11.16-vc6-headers.patch index fdf4e95..4f4013e 100644 --- a/compat/msvc600/cpython-3.11.16-vc6-headers.patch +++ b/compat/msvc600/cpython-3.11.16-vc6-headers.patch @@ -14026,8 +14026,26 @@ index 7e85720..64c63bc 100644 errors = PyUnicode_AsUTF8AndSize(fastargs[2], &errors_length); if (errors == NULL) { goto exit; +diff --git a/Objects/clinic/floatobject.c.h b/Objects/clinic/floatobject.c.h +index bf0748f..cbf2851 100644 +--- a/Objects/clinic/floatobject.c.h ++++ b/Objects/clinic/floatobject.c.h +@@ -270,12 +270,12 @@ float___getformat__(PyTypeObject *type, PyObject *arg) + { + PyObject *return_value = NULL; + const char *typestr; ++ Py_ssize_t typestr_length; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("__getformat__", "argument", "str", arg); + goto exit; + } +- Py_ssize_t typestr_length; + typestr = PyUnicode_AsUTF8AndSize(arg, &typestr_length); + if (typestr == NULL) { + goto exit; diff --git a/Objects/codeobject.c b/Objects/codeobject.c -index c4a0d9a..4d62228 100644 +index c4a0d9a..bb481b2 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -54,7 +54,9 @@ intern_strings(PyObject *tuple) @@ -14485,32 +14503,3659 @@ index c4a0d9a..4d62228 100644 _PyCode_InitAddressRange(co, &bounds); _PyCode_CheckLineNumber(addrq, &bounds); retreat(&bounds); +@@ -1028,14 +1065,17 @@ _PyLineTable_NextAddressRange(PyCodeAddressRange *range) + int + _PyLineTable_StartsLine(PyCodeAddressRange *range) + { ++ const uint8_t *ptr; ++ int code; ++ + if (range->ar_start <= 0) { + return 0; + } +- const uint8_t *ptr = range->opaque.lo_next; ++ ptr = range->opaque.lo_next; + do { + ptr--; + } while (((*ptr) & 128) == 0); +- int code = ((*ptr)>> 3) & 15; ++ code = ((*ptr)>> 3) & 15; + switch(code) { + case PY_CODE_LOCATION_INFO_LONG: + return 0; +@@ -1055,12 +1095,13 @@ _PyLineTable_StartsLine(PyCodeAddressRange *range) + static int + emit_pair(PyObject **bytes, int *offset, int a, int b) + { ++ unsigned char *lnotab; + Py_ssize_t len = PyBytes_GET_SIZE(*bytes); + if (*offset + 2 >= len) { + if (_PyBytes_Resize(bytes, len * 2) < 0) + return 0; + } +- unsigned char *lnotab = (unsigned char *) PyBytes_AS_STRING(*bytes); ++ lnotab = (unsigned char *) PyBytes_AS_STRING(*bytes); + lnotab += *offset; + *lnotab++ = a; + *lnotab++ = b; +@@ -1142,13 +1183,18 @@ static PyObject * + lineiter_next(lineiterator *li) + { + PyCodeAddressRange *bounds = &li->li_line; ++ PyObject *start; ++ PyObject *end; ++ PyObject *line; ++ PyObject *result; ++ + if (!_PyLineTable_NextAddressRange(bounds)) { + return NULL; + } +- PyObject *start = NULL; +- PyObject *end = NULL; +- PyObject *line = NULL; +- PyObject *result = PyTuple_New(3); ++ start = NULL; ++ end = NULL; ++ line = NULL; ++ result = PyTuple_New(3); + start = PyLong_FromLong(bounds->ar_start); + end = PyLong_FromLong(bounds->ar_end); + if (bounds->ar_line < 0) { +@@ -1345,13 +1391,16 @@ typedef struct { + int + _PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra) + { ++ PyCodeObject *o; ++ _PyCodeObjectExtra *co_extra; ++ + if (!PyCode_Check(code)) { + PyErr_BadInternalCall(); + return -1; + } + +- PyCodeObject *o = (PyCodeObject*) code; +- _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) o->co_extra; ++ o = (PyCodeObject*) code; ++ co_extra = (_PyCodeObjectExtra*) o->co_extra; + + if (co_extra == NULL || index < 0 || co_extra->ce_size <= index) { + *extra = NULL; +@@ -1367,6 +1416,10 @@ int + _PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra) + { + PyInterpreterState *interp = _PyInterpreterState_GET(); ++ PyCodeObject *o; ++ _PyCodeObjectExtra *co_extra; ++ Py_ssize_t i; ++ freefunc free; + + if (!PyCode_Check(code) || index < 0 || + index >= interp->co_extra_user_count) { +@@ -1374,11 +1427,11 @@ _PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra) + return -1; + } + +- PyCodeObject *o = (PyCodeObject*) code; +- _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra *) o->co_extra; ++ o = (PyCodeObject*) code; ++ co_extra = (_PyCodeObjectExtra *) o->co_extra; + + if (co_extra == NULL || co_extra->ce_size <= index) { +- Py_ssize_t i = (co_extra == NULL ? 0 : co_extra->ce_size); ++ i = (co_extra == NULL ? 0 : co_extra->ce_size); + co_extra = PyMem_Realloc( + co_extra, + sizeof(_PyCodeObjectExtra) + +@@ -1394,7 +1447,7 @@ _PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra) + } + + if (co_extra->ce_extras[index] != NULL) { +- freefunc free = interp->co_extra_freefuncs[index]; ++ free = interp->co_extra_freefuncs[index]; + if (free != NULL) { + free(co_extra->ce_extras[index]); + } +@@ -1448,7 +1501,9 @@ PyCode_GetFreevars(PyCodeObject *code) + static void + deopt_code(_Py_CODEUNIT *instructions, Py_ssize_t len) + { +- for (int i = 0; i < len; i++) { ++ int i; ++ ++ for (i = 0; i < len; i++) { + _Py_CODEUNIT instruction = instructions[i]; + int opcode = _PyOpcode_Deopt[_Py_OPCODE(instruction)]; + int caches = _PyOpcode_Caches[opcode]; +@@ -1462,10 +1517,12 @@ deopt_code(_Py_CODEUNIT *instructions, Py_ssize_t len) + PyObject * + _PyCode_GetCode(PyCodeObject *co) + { ++ PyObject *code; ++ + if (co->_co_code != NULL) { + return Py_NewRef(co->_co_code); + } +- PyObject *code = PyBytes_FromStringAndSize((const char *)_PyCode_CODE(co), ++ code = PyBytes_FromStringAndSize((const char *)_PyCode_CODE(co), + _PyCode_NBYTES(co)); + if (code == NULL) { + return NULL; +@@ -1610,8 +1667,9 @@ code_dealloc(PyCodeObject *co) + if (co->co_extra != NULL) { + PyInterpreterState *interp = _PyInterpreterState_GET(); + _PyCodeObjectExtra *co_extra = co->co_extra; ++ Py_ssize_t i; + +- for (Py_ssize_t i = 0; i < co_extra->ce_size; i++) { ++ for (i = 0; i < co_extra->ce_size; i++) { + freefunc free_extra = interp->co_extra_freefuncs[i]; + + if (free_extra != NULL) { +@@ -1670,6 +1728,7 @@ code_richcompare(PyObject *self, PyObject *other, int op) + int eq; + PyObject *consts1, *consts2; + PyObject *res; ++ int i; + + if ((op != Py_EQ && op != Py_NE) || + !PyCode_Check(self) || +@@ -1696,7 +1755,7 @@ code_richcompare(PyObject *self, PyObject *other, int op) + if (!eq) { + goto unequal; + } +- for (int i = 0; i < Py_SIZE(co); i++) { ++ for (i = 0; i < Py_SIZE(co); i++) { + _Py_CODEUNIT co_instr = _PyCode_CODE(co)[i]; + _Py_CODEUNIT cp_instr = _PyCode_CODE(cp)[i]; + _Py_SET_OPCODE(co_instr, _PyOpcode_Deopt[_Py_OPCODE(co_instr)]); +@@ -1760,6 +1819,7 @@ static Py_hash_t + code_hash(PyCodeObject *co) + { + Py_hash_t h, h0, h1, h2, h3; ++ Py_hash_t h4, h5; + h0 = PyObject_Hash(co->co_name); + if (h0 == -1) return -1; + h1 = PyObject_Hash(co->co_consts); +@@ -1768,11 +1828,11 @@ code_hash(PyCodeObject *co) + if (h2 == -1) return -1; + h3 = PyObject_Hash(co->co_localsplusnames); + if (h3 == -1) return -1; +- Py_hash_t h4 = PyObject_Hash(co->co_linetable); ++ h4 = PyObject_Hash(co->co_linetable); + if (h4 == -1) { + return -1; + } +- Py_hash_t h5 = PyObject_Hash(co->co_exceptiontable); ++ h5 = PyObject_Hash(co->co_exceptiontable); + if (h5 == -1) { + return -1; + } +@@ -1913,6 +1973,12 @@ code_replace_impl(PyCodeObject *self, int co_argcount, + PyObject *co_exceptiontable) + /*[clinic end generated code: output=e75c48a15def18b9 input=18e280e07846c122]*/ + { ++ PyObject *code; ++ PyCodeObject *co; ++ PyObject *varnames; ++ PyObject *cellvars; ++ PyObject *freevars; ++ + #define CHECK_INT_ARG(ARG) \ + if (ARG < 0) { \ + PyErr_SetString(PyExc_ValueError, \ +@@ -1930,7 +1996,7 @@ code_replace_impl(PyCodeObject *self, int co_argcount, + + #undef CHECK_INT_ARG + +- PyObject *code = NULL; ++ code = NULL; + if (co_code == NULL) { + code = _PyCode_GetCode(self); + if (code == NULL) { +@@ -1947,10 +2013,10 @@ code_replace_impl(PyCodeObject *self, int co_argcount, + return NULL; + } + +- PyCodeObject *co = NULL; +- PyObject *varnames = NULL; +- PyObject *cellvars = NULL; +- PyObject *freevars = NULL; ++ co = NULL; ++ varnames = NULL; ++ cellvars = NULL; ++ freevars = NULL; + if (co_varnames == NULL) { + varnames = get_localsplus_names(self, CO_FAST_LOCAL, self->co_nlocals); + if (varnames == NULL) { +diff --git a/Objects/descrobject.c b/Objects/descrobject.c +index 8369fed..227bd60 100644 +--- a/Objects/descrobject.c ++++ b/Objects/descrobject.c +@@ -106,6 +106,8 @@ descr_check(PyDescrObject *descr, PyObject *obj) + static PyObject * + classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) + { ++ PyTypeObject *cls; ++ + /* Ensure a valid type. Class methods ignore obj. */ + if (type == NULL) { + if (obj != NULL) +@@ -138,7 +140,7 @@ classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) + ((PyTypeObject *)type)->tp_name); + return NULL; + } +- PyTypeObject *cls = NULL; ++ cls = NULL; + if (descr->d_method->ml_flags & METH_METHOD) { + cls = descr->d_common.d_type; + } +@@ -271,9 +273,12 @@ getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value) + static inline int + method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) + { ++ PyObject *self; ++ PyObject *funcstr; ++ + assert(!PyErr_Occurred()); + if (nargs < 1) { +- PyObject *funcstr = _PyObject_FunctionStr(func); ++ funcstr = _PyObject_FunctionStr(func); + if (funcstr != NULL) { + PyErr_Format(PyExc_TypeError, + "unbound method %U needs an argument", funcstr); +@@ -281,12 +286,12 @@ method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObj + } + return -1; + } +- PyObject *self = args[0]; ++ self = args[0]; + if (descr_check((PyDescrObject *)func, self) < 0) { + return -1; + } + if (kwnames && PyTuple_GET_SIZE(kwnames)) { +- PyObject *funcstr = _PyObject_FunctionStr(func); ++ funcstr = _PyObject_FunctionStr(func); + if (funcstr != NULL) { + PyErr_Format(PyExc_TypeError, + "%U takes no keyword arguments", funcstr); +@@ -315,19 +320,22 @@ method_vectorcall_VARARGS( + { + PyThreadState *tstate = _PyThreadState_GET(); + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); ++ PyObject *argstuple; ++ PyCFunction meth; ++ PyObject *result; + if (method_check_args(func, args, nargs, kwnames)) { + return NULL; + } +- PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1); ++ argstuple = _PyTuple_FromArray(args+1, nargs-1); + if (argstuple == NULL) { + return NULL; + } +- PyCFunction meth = (PyCFunction)method_enter_call(tstate, func); ++ meth = (PyCFunction)method_enter_call(tstate, func); + if (meth == NULL) { + Py_DECREF(argstuple); + return NULL; + } +- PyObject *result = _PyCFunction_TrampolineCall( ++ result = _PyCFunction_TrampolineCall( + meth, args[0], argstuple); + Py_DECREF(argstuple); + _Py_LeaveRecursiveCallTstate(tstate); +@@ -340,23 +348,27 @@ method_vectorcall_VARARGS_KEYWORDS( + { + PyThreadState *tstate = _PyThreadState_GET(); + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); ++ PyObject *argstuple; ++ PyObject *result; ++ PyObject *kwdict; ++ PyCFunctionWithKeywords meth; + if (method_check_args(func, args, nargs, NULL)) { + return NULL; + } +- PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1); ++ argstuple = _PyTuple_FromArray(args+1, nargs-1); + if (argstuple == NULL) { + return NULL; + } +- PyObject *result = NULL; ++ result = NULL; + /* Create a temporary dict for keyword arguments */ +- PyObject *kwdict = NULL; ++ kwdict = NULL; + if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) > 0) { + kwdict = _PyStack_AsDict(args + nargs, kwnames); + if (kwdict == NULL) { + goto exit; + } + } +- PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords) ++ meth = (PyCFunctionWithKeywords) + method_enter_call(tstate, func); + if (meth == NULL) { + goto exit; +@@ -376,14 +388,16 @@ method_vectorcall_FASTCALL_KEYWORDS_METHOD( + { + PyThreadState *tstate = _PyThreadState_GET(); + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); ++ PyCMethod meth; ++ PyObject *result; + if (method_check_args(func, args, nargs, NULL)) { + return NULL; + } +- PyCMethod meth = (PyCMethod) method_enter_call(tstate, func); ++ meth = (PyCMethod) method_enter_call(tstate, func); + if (meth == NULL) { + return NULL; + } +- PyObject *result = meth(args[0], ++ result = meth(args[0], + ((PyMethodDescrObject *)func)->d_common.d_type, + args+1, nargs-1, kwnames); + _Py_LeaveRecursiveCall(); +@@ -396,15 +410,17 @@ method_vectorcall_FASTCALL( + { + PyThreadState *tstate = _PyThreadState_GET(); + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); ++ _PyCFunctionFast meth; ++ PyObject *result; + if (method_check_args(func, args, nargs, kwnames)) { + return NULL; + } +- _PyCFunctionFast meth = (_PyCFunctionFast) ++ meth = (_PyCFunctionFast) + method_enter_call(tstate, func); + if (meth == NULL) { + return NULL; + } +- PyObject *result = meth(args[0], args+1, nargs-1); ++ result = meth(args[0], args+1, nargs-1); + _Py_LeaveRecursiveCallTstate(tstate); + return result; + } +@@ -415,15 +431,17 @@ method_vectorcall_FASTCALL_KEYWORDS( + { + PyThreadState *tstate = _PyThreadState_GET(); + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); ++ _PyCFunctionFastWithKeywords meth; ++ PyObject *result; + if (method_check_args(func, args, nargs, NULL)) { + return NULL; + } +- _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords) ++ meth = (_PyCFunctionFastWithKeywords) + method_enter_call(tstate, func); + if (meth == NULL) { + return NULL; + } +- PyObject *result = meth(args[0], args+1, nargs-1, kwnames); ++ result = meth(args[0], args+1, nargs-1, kwnames); + _Py_LeaveRecursiveCallTstate(tstate); + return result; + } +@@ -434,11 +452,14 @@ method_vectorcall_NOARGS( + { + PyThreadState *tstate = _PyThreadState_GET(); + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); ++ PyObject *funcstr; ++ PyCFunction meth; ++ PyObject *result; + if (method_check_args(func, args, nargs, kwnames)) { + return NULL; + } + if (nargs != 1) { +- PyObject *funcstr = _PyObject_FunctionStr(func); ++ funcstr = _PyObject_FunctionStr(func); + if (funcstr != NULL) { + PyErr_Format(PyExc_TypeError, + "%U takes no arguments (%zd given)", funcstr, nargs-1); +@@ -446,11 +467,11 @@ method_vectorcall_NOARGS( + } + return NULL; + } +- PyCFunction meth = (PyCFunction)method_enter_call(tstate, func); ++ meth = (PyCFunction)method_enter_call(tstate, func); + if (meth == NULL) { + return NULL; + } +- PyObject *result = _PyCFunction_TrampolineCall(meth, args[0], NULL); ++ result = _PyCFunction_TrampolineCall(meth, args[0], NULL); + _Py_LeaveRecursiveCallTstate(tstate); + return result; + } +@@ -461,11 +482,14 @@ method_vectorcall_O( + { + PyThreadState *tstate = _PyThreadState_GET(); + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); ++ PyObject *funcstr; ++ PyCFunction meth; ++ PyObject *result; + if (method_check_args(func, args, nargs, kwnames)) { + return NULL; + } + if (nargs != 2) { +- PyObject *funcstr = _PyObject_FunctionStr(func); ++ funcstr = _PyObject_FunctionStr(func); + if (funcstr != NULL) { + PyErr_Format(PyExc_TypeError, + "%U takes exactly one argument (%zd given)", +@@ -474,11 +498,11 @@ method_vectorcall_O( + } + return NULL; + } +- PyCFunction meth = (PyCFunction)method_enter_call(tstate, func); ++ meth = (PyCFunction)method_enter_call(tstate, func); + if (meth == NULL) { + return NULL; + } +- PyObject *result = _PyCFunction_TrampolineCall(meth, args[0], args[1]); ++ result = _PyCFunction_TrampolineCall(meth, args[0], args[1]); + _Py_LeaveRecursiveCallTstate(tstate); + return result; + } +@@ -496,7 +520,12 @@ static PyObject * + classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args, + PyObject *kwds) + { +- Py_ssize_t argc = PyTuple_GET_SIZE(args); ++ Py_ssize_t argc; ++ PyObject *self; ++ PyObject *bound; ++ PyObject *res; ++ ++ argc = PyTuple_GET_SIZE(args); + if (argc < 1) { + PyErr_Format(PyExc_TypeError, + "descriptor '%V' of '%.100s' " +@@ -505,12 +534,12 @@ classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args, + PyDescr_TYPE(descr)->tp_name); + return NULL; + } +- PyObject *self = PyTuple_GET_ITEM(args, 0); +- PyObject *bound = classmethod_get(descr, NULL, self); ++ self = PyTuple_GET_ITEM(args, 0); ++ bound = classmethod_get(descr, NULL, self); + if (bound == NULL) { + return NULL; + } +- PyObject *res = PyObject_VectorcallDict(bound, _PyTuple_ITEMS(args)+1, ++ res = PyObject_VectorcallDict(bound, _PyTuple_ITEMS(args)+1, + argc-1, kwds); + Py_DECREF(bound); + return res; +@@ -920,6 +949,7 @@ descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name) + PyObject * + PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method) + { ++ PyMethodDescrObject *descr; + /* Figure out correct vectorcall function to use */ + vectorcallfunc vectorcall; + switch (method->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | +@@ -952,8 +982,6 @@ PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method) + return NULL; + } + +- PyMethodDescrObject *descr; +- + descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type, + type, method->ml_name); + if (descr != NULL) { +@@ -1066,10 +1094,21 @@ mappingproxy_ior(PyObject *self, PyObject *Py_UNUSED(other)) + "'|=' is not supported by %s; use '|' instead", Py_TYPE(self)->tp_name); + } + ++#if !defined(MS_WINDOWS) || !defined(_MSC_VER) || _MSC_VER >= 1300 + static PyNumberMethods mappingproxy_as_number = { + .nb_or = mappingproxy_or, + .nb_inplace_or = mappingproxy_ior, + }; ++#else ++static PyNumberMethods mappingproxy_as_number = {0}; ++ ++void ++_PyDesc_InitTypes(void) ++{ ++ mappingproxy_as_number.nb_or = mappingproxy_or; ++ mappingproxy_as_number.nb_inplace_or = mappingproxy_ior; ++} ++#endif + + static int + mappingproxy_contains(mappingproxyobject *pp, PyObject *key) +@@ -1558,6 +1597,9 @@ PyDoc_STRVAR(set_name_doc, + + static PyObject * + property_set_name(PyObject *self, PyObject *args) { ++ propertyobject *prop; ++ PyObject *name; ++ + if (PyTuple_GET_SIZE(args) != 2) { + PyErr_Format( + PyExc_TypeError, +@@ -1566,8 +1608,8 @@ property_set_name(PyObject *self, PyObject *args) { + return NULL; + } + +- propertyobject *prop = (propertyobject *)self; +- PyObject *name = PyTuple_GET_ITEM(args, 1); ++ prop = (propertyobject *)self; ++ name = PyTuple_GET_ITEM(args, 1); + + Py_XINCREF(name); + Py_XSETREF(prop->prop_name, name); +@@ -1601,12 +1643,14 @@ property_dealloc(PyObject *self) + static PyObject * + property_descr_get(PyObject *self, PyObject *obj, PyObject *type) + { ++ propertyobject *gs; ++ + if (obj == NULL || obj == Py_None) { + Py_INCREF(self); + return self; + } + +- propertyobject *gs = (propertyobject *)self; ++ gs = (propertyobject *)self; + if (gs->prop_get == NULL) { + PyObject *qualname = PyType_GetQualName(Py_TYPE(obj)); + if (gs->prop_name != NULL && qualname != NULL) { +diff --git a/Objects/dictobject.c b/Objects/dictobject.c +index 0e9c6d2..c1ed9d8 100644 +--- a/Objects/dictobject.c ++++ b/Objects/dictobject.c +@@ -504,16 +504,31 @@ dump_entries(PyDictKeysObject *dk) + int + _PyDict_CheckConsistency(PyObject *op, int check_content) + { ++ PyDictObject *mp; ++ PyDictKeysObject *keys; ++ int splitted; ++ Py_ssize_t usable; ++ Py_ssize_t i; ++ Py_ssize_t ix; ++ PyDictKeyEntry *key_entries; ++ PyDictKeyEntry *dict_entry; ++ PyDictUnicodeEntry *unicode_entries; ++ PyDictUnicodeEntry *unicode_entry; ++ PyObject *key; ++ Py_hash_t hash; ++ int duplicate_check; ++ int index; ++ + #define CHECK(expr) \ + do { if (!(expr)) { _PyObject_ASSERT_FAILED_MSG(op, Py_STRINGIFY(expr)); } } while (0) + + assert(op != NULL); + CHECK(PyDict_Check(op)); +- PyDictObject *mp = (PyDictObject *)op; ++ mp = (PyDictObject *)op; + +- PyDictKeysObject *keys = mp->ma_keys; +- int splitted = _PyDict_HasSplitTable(mp); +- Py_ssize_t usable = USABLE_FRACTION(DK_SIZE(keys)); ++ keys = mp->ma_keys; ++ splitted = _PyDict_HasSplitTable(mp); ++ usable = USABLE_FRACTION(DK_SIZE(keys)); + + CHECK(0 <= mp->ma_used && mp->ma_used <= usable); + CHECK(0 <= keys->dk_usable && keys->dk_usable <= usable); +@@ -531,46 +546,46 @@ _PyDict_CheckConsistency(PyObject *op, int check_content) + } + + if (check_content) { +- for (Py_ssize_t i=0; i < DK_SIZE(keys); i++) { +- Py_ssize_t ix = dictkeys_get_index(keys, i); ++ for (i=0; i < DK_SIZE(keys); i++) { ++ ix = dictkeys_get_index(keys, i); + CHECK(DKIX_DUMMY <= ix && ix <= usable); + } + + if (keys->dk_kind == DICT_KEYS_GENERAL) { +- PyDictKeyEntry *entries = DK_ENTRIES(keys); +- for (Py_ssize_t i=0; i < usable; i++) { +- PyDictKeyEntry *entry = &entries[i]; +- PyObject *key = entry->me_key; ++ key_entries = DK_ENTRIES(keys); ++ for (i=0; i < usable; i++) { ++ dict_entry = &key_entries[i]; ++ key = dict_entry->me_key; + + if (key != NULL) { + /* test_dict fails if PyObject_Hash() is called again */ +- CHECK(entry->me_hash != -1); +- CHECK(entry->me_value != NULL); ++ CHECK(dict_entry->me_hash != -1); ++ CHECK(dict_entry->me_value != NULL); + + if (PyUnicode_CheckExact(key)) { +- Py_hash_t hash = unicode_get_hash(key); +- CHECK(entry->me_hash == hash); ++ hash = unicode_get_hash(key); ++ CHECK(dict_entry->me_hash == hash); + } + } + } + } + else { +- PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys); +- for (Py_ssize_t i=0; i < usable; i++) { +- PyDictUnicodeEntry *entry = &entries[i]; +- PyObject *key = entry->me_key; ++ unicode_entries = DK_UNICODE_ENTRIES(keys); ++ for (i=0; i < usable; i++) { ++ unicode_entry = &unicode_entries[i]; ++ key = unicode_entry->me_key; + + if (key != NULL) { + CHECK(PyUnicode_CheckExact(key)); +- Py_hash_t hash = unicode_get_hash(key); ++ hash = unicode_get_hash(key); + CHECK(hash != -1); + if (!splitted) { +- CHECK(entry->me_value != NULL); ++ CHECK(unicode_entry->me_value != NULL); + } + } + + if (splitted) { +- CHECK(entry->me_value == NULL); ++ CHECK(unicode_entry->me_value == NULL); + } + } + } +@@ -578,9 +593,9 @@ _PyDict_CheckConsistency(PyObject *op, int check_content) + if (splitted) { + CHECK(mp->ma_used <= SHARED_KEYS_MAX_SIZE); + /* splitted table */ +- int duplicate_check = 0; +- for (Py_ssize_t i=0; i < mp->ma_used; i++) { +- int index = get_index_from_order(mp, i); ++ duplicate_check = 0; ++ for (i=0; i < mp->ma_used; i++) { ++ index = get_index_from_order(mp, i); + CHECK((duplicate_check & (1<ma_values->values[index] != NULL); +@@ -600,6 +615,9 @@ new_keys_object(uint8_t log2_size, bool unicode) + Py_ssize_t usable; + int log2_bytes; + size_t entry_size = unicode ? sizeof(PyDictUnicodeEntry) : sizeof(PyDictKeyEntry); ++#if PyDict_MAXFREELIST > 0 ++ struct _Py_dict_state *state; ++#endif + + assert(log2_size >= PyDict_LOG_MINSIZE); + +@@ -620,7 +638,7 @@ new_keys_object(uint8_t log2_size, bool unicode) + } + + #if PyDict_MAXFREELIST > 0 +- struct _Py_dict_state *state = get_dict_state(); ++ state = get_dict_state(); + #ifdef Py_DEBUG + // new_keys_object() must not be called after _PyDict_Fini() + assert(state->keys_numfree != -1); +@@ -658,25 +676,30 @@ new_keys_object(uint8_t log2_size, bool unicode) + static void + free_keys_object(PyDictKeysObject *keys) + { ++ PyDictUnicodeEntry *unicode_entries; ++ PyDictKeyEntry *key_entries; ++ Py_ssize_t i, n; ++#if PyDict_MAXFREELIST > 0 ++ struct _Py_dict_state *state; ++#endif ++ + assert(keys != Py_EMPTY_KEYS); + if (DK_IS_UNICODE(keys)) { +- PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys); +- Py_ssize_t i, n; ++ unicode_entries = DK_UNICODE_ENTRIES(keys); + for (i = 0, n = keys->dk_nentries; i < n; i++) { +- Py_XDECREF(entries[i].me_key); +- Py_XDECREF(entries[i].me_value); ++ Py_XDECREF(unicode_entries[i].me_key); ++ Py_XDECREF(unicode_entries[i].me_value); + } + } + else { +- PyDictKeyEntry *entries = DK_ENTRIES(keys); +- Py_ssize_t i, n; ++ key_entries = DK_ENTRIES(keys); + for (i = 0, n = keys->dk_nentries; i < n; i++) { +- Py_XDECREF(entries[i].me_key); +- Py_XDECREF(entries[i].me_value); ++ Py_XDECREF(key_entries[i].me_key); ++ Py_XDECREF(key_entries[i].me_value); + } + } + #if PyDict_MAXFREELIST > 0 +- struct _Py_dict_state *state = get_dict_state(); ++ state = get_dict_state(); + #ifdef Py_DEBUG + // free_keys_object() must not be called after _PyDict_Fini() + assert(state->keys_numfree != -1); +@@ -695,11 +718,15 @@ free_keys_object(PyDictKeysObject *keys) + static inline PyDictValues* + new_values(Py_ssize_t size) + { ++ size_t prefix_size; ++ size_t n; ++ uint8_t *mem; ++ + assert(size > 0); +- size_t prefix_size = _Py_SIZE_ROUND_UP(size+2, sizeof(PyObject *)); ++ prefix_size = _Py_SIZE_ROUND_UP(size+2, sizeof(PyObject *)); + assert(prefix_size < 256); +- size_t n = prefix_size + size * sizeof(PyObject *); +- uint8_t *mem = PyMem_Malloc(n); ++ n = prefix_size + size * sizeof(PyObject *); ++ mem = PyMem_Malloc(n); + if (mem == NULL) { + return NULL; + } +@@ -720,9 +747,12 @@ static PyObject * + new_dict(PyDictKeysObject *keys, PyDictValues *values, Py_ssize_t used, int free_values_on_failure) + { + PyDictObject *mp; ++#if PyDict_MAXFREELIST > 0 ++ struct _Py_dict_state *state; ++#endif + assert(keys != NULL); + #if PyDict_MAXFREELIST > 0 +- struct _Py_dict_state *state = get_dict_state(); ++ state = get_dict_state(); + #ifdef Py_DEBUG + // new_dict() must not be called after _PyDict_Fini() + assert(state->numfree != -1); +@@ -784,13 +814,23 @@ new_dict_with_shared_keys(PyDictKeysObject *keys) + static PyDictKeysObject * + clone_combined_dict_keys(PyDictObject *orig) + { ++ size_t keys_size; ++ PyDictKeysObject *keys; ++ PyObject **pkey; ++ PyObject **pvalue; ++ size_t offs; ++ Py_ssize_t n; ++ Py_ssize_t i; ++ PyDictUnicodeEntry *unicode_ep0; ++ PyDictKeyEntry *key_ep0; ++ + assert(PyDict_Check(orig)); + assert(Py_TYPE(orig)->tp_iter == (getiterfunc)dict_iter); + assert(orig->ma_values == NULL); + assert(orig->ma_keys->dk_refcnt == 1); + +- Py_ssize_t keys_size = _PyDict_KeysSize(orig->ma_keys); +- PyDictKeysObject *keys = PyObject_Malloc(keys_size); ++ keys_size = _PyDict_KeysSize(orig->ma_keys); ++ keys = PyObject_Malloc(keys_size); + if (keys == NULL) { + PyErr_NoMemory(); + return NULL; +@@ -801,23 +841,21 @@ clone_combined_dict_keys(PyDictObject *orig) + /* After copying key/value pairs, we need to incref all + keys and values and they are about to be co-owned by a + new dict object. */ +- PyObject **pkey, **pvalue; +- size_t offs; + if (DK_IS_UNICODE(orig->ma_keys)) { +- PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(keys); +- pkey = &ep0->me_key; +- pvalue = &ep0->me_value; ++ unicode_ep0 = DK_UNICODE_ENTRIES(keys); ++ pkey = &unicode_ep0->me_key; ++ pvalue = &unicode_ep0->me_value; + offs = sizeof(PyDictUnicodeEntry) / sizeof(PyObject*); + } + else { +- PyDictKeyEntry *ep0 = DK_ENTRIES(keys); +- pkey = &ep0->me_key; +- pvalue = &ep0->me_value; ++ key_ep0 = DK_ENTRIES(keys); ++ pkey = &key_ep0->me_key; ++ pvalue = &key_ep0->me_value; + offs = sizeof(PyDictKeyEntry) / sizeof(PyObject*); + } + +- Py_ssize_t n = keys->dk_nentries; +- for (Py_ssize_t i = 0; i < n; i++) { ++ n = keys->dk_nentries; ++ for (i = 0; i < n; i++) { + PyObject *value = *pvalue; + if (value != NULL) { + Py_INCREF(value); +@@ -875,6 +913,7 @@ unicodekeys_lookup_generic(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key + size_t perturb = hash; + size_t i = (size_t)hash & mask; + Py_ssize_t ix; ++ int cmp; + for (;;) { + ix = dictkeys_get_index(dk, i); + if (ix >= 0) { +@@ -887,7 +926,7 @@ unicodekeys_lookup_generic(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key + if (unicode_get_hash(ep->me_key) == hash) { + PyObject *startkey = ep->me_key; + Py_INCREF(startkey); +- int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); ++ cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); + Py_DECREF(startkey); + if (cmp < 0) { + return DKIX_ERROR; +@@ -965,6 +1004,7 @@ dictkeys_generic_lookup(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key, P + size_t perturb = hash; + size_t i = (size_t)hash & mask; + Py_ssize_t ix; ++ int cmp; + for (;;) { + ix = dictkeys_get_index(dk, i); + if (ix >= 0) { +@@ -976,7 +1016,7 @@ dictkeys_generic_lookup(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key, P + if (ep->me_hash == hash) { + PyObject *startkey = ep->me_key; + Py_INCREF(startkey); +- int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); ++ cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); + Py_DECREF(startkey); + if (cmp < 0) { + return DKIX_ERROR; +@@ -1010,11 +1050,14 @@ dictkeys_generic_lookup(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key, P + Py_ssize_t + _PyDictKeys_StringLookup(PyDictKeysObject* dk, PyObject *key) + { +- DictKeysKind kind = dk->dk_kind; ++ DictKeysKind kind; ++ Py_hash_t hash; ++ ++ kind = dk->dk_kind; + if (!PyUnicode_CheckExact(key) || kind == DICT_KEYS_GENERAL) { + return DKIX_ERROR; + } +- Py_hash_t hash = unicode_get_hash(key); ++ hash = unicode_get_hash(key); + if (hash == -1) { + hash = PyUnicode_Type.tp_hash(key); + if (hash == -1) { +@@ -1167,12 +1210,17 @@ _PyDict_MaybeUntrack(PyObject *op) + static Py_ssize_t + find_empty_slot(PyDictKeysObject *keys, Py_hash_t hash) + { ++ size_t mask; ++ size_t i; ++ size_t perturb; ++ Py_ssize_t ix; ++ + assert(keys != NULL); + +- const size_t mask = DK_MASK(keys); +- size_t i = hash & mask; +- Py_ssize_t ix = dictkeys_get_index(keys, i); +- for (size_t perturb = hash; ix >= 0;) { ++ mask = DK_MASK(keys); ++ i = hash & mask; ++ ix = dictkeys_get_index(keys, i); ++ for (perturb = hash; ix >= 0;) { + perturb >>= PERTURB_SHIFT; + i = (i*5 + perturb + 1) & mask; + ix = dictkeys_get_index(keys, i); +@@ -1189,8 +1237,13 @@ insertion_resize(PyDictObject *mp, int unicode) + static Py_ssize_t + insert_into_dictkeys(PyDictKeysObject *keys, PyObject *name) + { ++ Py_hash_t hash; ++ Py_ssize_t ix; ++ Py_ssize_t hashpos; ++ PyDictUnicodeEntry *ep; ++ + assert(PyUnicode_CheckExact(name)); +- Py_hash_t hash = unicode_get_hash(name); ++ hash = unicode_get_hash(name); + if (hash == -1) { + hash = PyUnicode_Type.tp_hash(name); + if (hash == -1) { +@@ -1198,7 +1251,7 @@ insert_into_dictkeys(PyDictKeysObject *keys, PyObject *name) + return DKIX_EMPTY; + } + } +- Py_ssize_t ix = unicodekeys_lookup_unicode(keys, name, hash); ++ ix = unicodekeys_lookup_unicode(keys, name, hash); + if (ix == DKIX_EMPTY) { + if (keys->dk_usable <= 0) { + return DKIX_EMPTY; +@@ -1206,9 +1259,9 @@ insert_into_dictkeys(PyDictKeysObject *keys, PyObject *name) + Py_INCREF(name); + /* Insert into new slot. */ + keys->dk_version = 0; +- Py_ssize_t hashpos = find_empty_slot(keys, hash); ++ hashpos = find_empty_slot(keys, hash); + ix = keys->dk_nentries; +- PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(keys)[ix]; ++ ep = &DK_UNICODE_ENTRIES(keys)[ix]; + dictkeys_set_index(keys, hashpos, ix); + assert(ep->me_key == NULL); + ep->me_key = name; +@@ -1229,6 +1282,8 @@ static int + insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) + { + PyObject *old_value; ++ Py_ssize_t ix; ++ Py_ssize_t hashpos; + + if (DK_IS_UNICODE(mp->ma_keys) && !PyUnicode_CheckExact(key)) { + if (insertion_resize(mp, 0) < 0) +@@ -1236,7 +1291,7 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) + assert(mp->ma_keys->dk_kind == DICT_KEYS_GENERAL); + } + +- Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &old_value); ++ ix = _Py_dict_lookup(mp, key, hash, &old_value); + if (ix == DKIX_ERROR) + goto Fail; + +@@ -1252,7 +1307,7 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) + goto Fail; + } + +- Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash); ++ hashpos = find_empty_slot(mp->ma_keys, hash); + dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries); + + if (DK_IS_UNICODE(mp->ma_keys)) { +@@ -1321,10 +1376,16 @@ static int + insert_to_emptydict(PyDictObject *mp, PyObject *key, Py_hash_t hash, + PyObject *value) + { ++ int unicode; ++ PyDictKeysObject *newkeys; ++ size_t hashpos; ++ PyDictUnicodeEntry *unicode_ep; ++ PyDictKeyEntry *key_ep; ++ + assert(mp->ma_keys == Py_EMPTY_KEYS); + +- int unicode = PyUnicode_CheckExact(key); +- PyDictKeysObject *newkeys = new_keys_object(PyDict_LOG_MINSIZE, unicode); ++ unicode = PyUnicode_CheckExact(key); ++ newkeys = new_keys_object(PyDict_LOG_MINSIZE, unicode); + if (newkeys == NULL) { + Py_DECREF(key); + Py_DECREF(value); +@@ -1336,7 +1397,7 @@ insert_to_emptydict(PyDictObject *mp, PyObject *key, Py_hash_t hash, + + MAINTAIN_TRACKING(mp, key, value); + +- size_t hashpos = (size_t)hash & (PyDict_MINSIZE-1); ++ hashpos = (size_t)hash & (PyDict_MINSIZE-1); + dictkeys_set_index(mp->ma_keys, hashpos, 0); + if (unicode) { + PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(mp->ma_keys); +@@ -1362,11 +1423,17 @@ Internal routine used by dictresize() to build a hashtable of entries. + static void + build_indices_generic(PyDictKeysObject *keys, PyDictKeyEntry *ep, Py_ssize_t n) + { +- size_t mask = DK_MASK(keys); +- for (Py_ssize_t ix = 0; ix != n; ix++, ep++) { +- Py_hash_t hash = ep->me_hash; +- size_t i = hash & mask; +- for (size_t perturb = hash; dictkeys_get_index(keys, i) != DKIX_EMPTY;) { ++ size_t mask; ++ size_t i; ++ size_t perturb; ++ Py_ssize_t ix; ++ Py_hash_t hash; ++ ++ mask = DK_MASK(keys); ++ for (ix = 0; ix != n; ix++, ep++) { ++ hash = ep->me_hash; ++ i = hash & mask; ++ for (perturb = hash; dictkeys_get_index(keys, i) != DKIX_EMPTY;) { + perturb >>= PERTURB_SHIFT; + i = mask & (i*5 + perturb + 1); + } +@@ -1377,12 +1444,18 @@ build_indices_generic(PyDictKeysObject *keys, PyDictKeyEntry *ep, Py_ssize_t n) + static void + build_indices_unicode(PyDictKeysObject *keys, PyDictUnicodeEntry *ep, Py_ssize_t n) + { +- size_t mask = DK_MASK(keys); +- for (Py_ssize_t ix = 0; ix != n; ix++, ep++) { +- Py_hash_t hash = unicode_get_hash(ep->me_key); ++ size_t mask; ++ size_t i; ++ size_t perturb; ++ Py_ssize_t ix; ++ Py_hash_t hash; ++ ++ mask = DK_MASK(keys); ++ for (ix = 0; ix != n; ix++, ep++) { ++ hash = unicode_get_hash(ep->me_key); + assert(hash != -1); +- size_t i = hash & mask; +- for (size_t perturb = hash; dictkeys_get_index(keys, i) != DKIX_EMPTY;) { ++ i = hash & mask; ++ for (perturb = hash; dictkeys_get_index(keys, i) != DKIX_EMPTY;) { + perturb >>= PERTURB_SHIFT; + i = mask & (i*5 + perturb + 1); + } +@@ -1409,6 +1482,18 @@ dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode) + { + PyDictKeysObject *oldkeys; + PyDictValues *oldvalues; ++ Py_ssize_t numentries; ++ Py_ssize_t i; ++ int index; ++ PyDictUnicodeEntry *old_unicode_entries; ++ PyDictUnicodeEntry *new_unicode_entries; ++ PyDictUnicodeEntry *unicode_entry; ++ PyDictKeyEntry *old_key_entries; ++ PyDictKeyEntry *new_key_entries; ++ PyDictKeyEntry *key_entry; ++#if PyDict_MAXFREELIST > 0 ++ struct _Py_dict_state *state; ++#endif + + if (log2_newsize >= SIZEOF_SIZE_T*8) { + PyErr_NoMemory(); +@@ -1437,40 +1522,40 @@ dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode) + // New table must be large enough. + assert(mp->ma_keys->dk_usable >= mp->ma_used); + +- Py_ssize_t numentries = mp->ma_used; ++ numentries = mp->ma_used; + + if (oldvalues != NULL) { +- PyDictUnicodeEntry *oldentries = DK_UNICODE_ENTRIES(oldkeys); ++ old_unicode_entries = DK_UNICODE_ENTRIES(oldkeys); + /* Convert split table into new combined table. + * We must incref keys; we can transfer values. + */ + if (mp->ma_keys->dk_kind == DICT_KEYS_GENERAL) { + // split -> generic +- PyDictKeyEntry *newentries = DK_ENTRIES(mp->ma_keys); ++ new_key_entries = DK_ENTRIES(mp->ma_keys); + +- for (Py_ssize_t i = 0; i < numentries; i++) { +- int index = get_index_from_order(mp, i); +- PyDictUnicodeEntry *ep = &oldentries[index]; ++ for (i = 0; i < numentries; i++) { ++ index = get_index_from_order(mp, i); ++ unicode_entry = &old_unicode_entries[index]; + assert(oldvalues->values[index] != NULL); +- Py_INCREF(ep->me_key); +- newentries[i].me_key = ep->me_key; +- newentries[i].me_hash = unicode_get_hash(ep->me_key); +- newentries[i].me_value = oldvalues->values[index]; ++ Py_INCREF(unicode_entry->me_key); ++ new_key_entries[i].me_key = unicode_entry->me_key; ++ new_key_entries[i].me_hash = unicode_get_hash(unicode_entry->me_key); ++ new_key_entries[i].me_value = oldvalues->values[index]; + } +- build_indices_generic(mp->ma_keys, newentries, numentries); ++ build_indices_generic(mp->ma_keys, new_key_entries, numentries); + } + else { // split -> combined unicode +- PyDictUnicodeEntry *newentries = DK_UNICODE_ENTRIES(mp->ma_keys); ++ new_unicode_entries = DK_UNICODE_ENTRIES(mp->ma_keys); + +- for (Py_ssize_t i = 0; i < numentries; i++) { +- int index = get_index_from_order(mp, i); +- PyDictUnicodeEntry *ep = &oldentries[index]; ++ for (i = 0; i < numentries; i++) { ++ index = get_index_from_order(mp, i); ++ unicode_entry = &old_unicode_entries[index]; + assert(oldvalues->values[index] != NULL); +- Py_INCREF(ep->me_key); +- newentries[i].me_key = ep->me_key; +- newentries[i].me_value = oldvalues->values[index]; ++ Py_INCREF(unicode_entry->me_key); ++ new_unicode_entries[i].me_key = unicode_entry->me_key; ++ new_unicode_entries[i].me_value = oldvalues->values[index]; + } +- build_indices_unicode(mp->ma_keys, newentries, numentries); ++ build_indices_unicode(mp->ma_keys, new_unicode_entries, numentries); + } + dictkeys_decref(oldkeys); + mp->ma_values = NULL; +@@ -1480,50 +1565,50 @@ dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode) + if (oldkeys->dk_kind == DICT_KEYS_GENERAL) { + // generic -> generic + assert(mp->ma_keys->dk_kind == DICT_KEYS_GENERAL); +- PyDictKeyEntry *oldentries = DK_ENTRIES(oldkeys); +- PyDictKeyEntry *newentries = DK_ENTRIES(mp->ma_keys); ++ old_key_entries = DK_ENTRIES(oldkeys); ++ new_key_entries = DK_ENTRIES(mp->ma_keys); + if (oldkeys->dk_nentries == numentries) { +- memcpy(newentries, oldentries, numentries * sizeof(PyDictKeyEntry)); ++ memcpy(new_key_entries, old_key_entries, numentries * sizeof(PyDictKeyEntry)); + } + else { +- PyDictKeyEntry *ep = oldentries; +- for (Py_ssize_t i = 0; i < numentries; i++) { +- while (ep->me_value == NULL) +- ep++; +- newentries[i] = *ep++; ++ key_entry = old_key_entries; ++ for (i = 0; i < numentries; i++) { ++ while (key_entry->me_value == NULL) ++ key_entry++; ++ new_key_entries[i] = *key_entry++; + } + } +- build_indices_generic(mp->ma_keys, newentries, numentries); ++ build_indices_generic(mp->ma_keys, new_key_entries, numentries); + } + else { // oldkeys is combined unicode +- PyDictUnicodeEntry *oldentries = DK_UNICODE_ENTRIES(oldkeys); ++ old_unicode_entries = DK_UNICODE_ENTRIES(oldkeys); + if (unicode) { // combined unicode -> combined unicode +- PyDictUnicodeEntry *newentries = DK_UNICODE_ENTRIES(mp->ma_keys); ++ new_unicode_entries = DK_UNICODE_ENTRIES(mp->ma_keys); + if (oldkeys->dk_nentries == numentries && mp->ma_keys->dk_kind == DICT_KEYS_UNICODE) { +- memcpy(newentries, oldentries, numentries * sizeof(PyDictUnicodeEntry)); ++ memcpy(new_unicode_entries, old_unicode_entries, numentries * sizeof(PyDictUnicodeEntry)); + } + else { +- PyDictUnicodeEntry *ep = oldentries; +- for (Py_ssize_t i = 0; i < numentries; i++) { +- while (ep->me_value == NULL) +- ep++; +- newentries[i] = *ep++; ++ unicode_entry = old_unicode_entries; ++ for (i = 0; i < numentries; i++) { ++ while (unicode_entry->me_value == NULL) ++ unicode_entry++; ++ new_unicode_entries[i] = *unicode_entry++; + } + } +- build_indices_unicode(mp->ma_keys, newentries, numentries); ++ build_indices_unicode(mp->ma_keys, new_unicode_entries, numentries); + } + else { // combined unicode -> generic +- PyDictKeyEntry *newentries = DK_ENTRIES(mp->ma_keys); +- PyDictUnicodeEntry *ep = oldentries; +- for (Py_ssize_t i = 0; i < numentries; i++) { +- while (ep->me_value == NULL) +- ep++; +- newentries[i].me_key = ep->me_key; +- newentries[i].me_hash = unicode_get_hash(ep->me_key); +- newentries[i].me_value = ep->me_value; +- ep++; ++ new_key_entries = DK_ENTRIES(mp->ma_keys); ++ unicode_entry = old_unicode_entries; ++ for (i = 0; i < numentries; i++) { ++ while (unicode_entry->me_value == NULL) ++ unicode_entry++; ++ new_key_entries[i].me_key = unicode_entry->me_key; ++ new_key_entries[i].me_hash = unicode_get_hash(unicode_entry->me_key); ++ new_key_entries[i].me_value = unicode_entry->me_value; ++ unicode_entry++; + } +- build_indices_generic(mp->ma_keys, newentries, numentries); ++ build_indices_generic(mp->ma_keys, new_key_entries, numentries); + } + } + +@@ -1540,7 +1625,7 @@ dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode) + assert(oldkeys->dk_kind != DICT_KEYS_SPLIT); + assert(oldkeys->dk_refcnt == 1); + #if PyDict_MAXFREELIST > 0 +- struct _Py_dict_state *state = get_dict_state(); ++ state = get_dict_state(); + #ifdef Py_DEBUG + // dictresize() must not be called after _PyDict_Fini() + assert(state->keys_numfree != -1); +@@ -1607,8 +1692,11 @@ _PyDict_FromItems(PyObject *const *keys, Py_ssize_t keys_offset, + { + bool unicode = true; + PyObject *const *ks = keys; ++ PyObject *const *vs; ++ PyObject *dict; ++ Py_ssize_t i; + +- for (Py_ssize_t i = 0; i < length; i++) { ++ for (i = 0; i < length; i++) { + if (!PyUnicode_CheckExact(*ks)) { + unicode = false; + break; +@@ -1616,15 +1704,15 @@ _PyDict_FromItems(PyObject *const *keys, Py_ssize_t keys_offset, + ks += keys_offset; + } + +- PyObject *dict = dict_new_presized(length, unicode); ++ dict = dict_new_presized(length, unicode); + if (dict == NULL) { + return NULL; + } + + ks = keys; +- PyObject *const *vs = values; ++ vs = values; + +- for (Py_ssize_t i = 0; i < length; i++) { ++ for (i = 0; i < length; i++) { + PyObject *key = *ks; + PyObject *value = *vs; + if (PyDict_SetItem(dict, key, value) < 0) { +@@ -1651,12 +1739,18 @@ _PyDict_FromItems(PyObject *const *keys, Py_ssize_t keys_offset, + PyObject * + PyDict_GetItem(PyObject *op, PyObject *key) + { ++ PyDictObject *mp; ++ Py_hash_t hash; ++ PyThreadState *tstate; ++ PyObject *exc_type, *exc_value, *exc_tb; ++ PyObject *value; ++ Py_ssize_t ix; ++ + if (!PyDict_Check(op)) { + return NULL; + } +- PyDictObject *mp = (PyDictObject *)op; ++ mp = (PyDictObject *)op; + +- Py_hash_t hash; + if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) { + hash = PyObject_Hash(key); + if (hash == -1) { +@@ -1665,7 +1759,7 @@ PyDict_GetItem(PyObject *op, PyObject *key) + } + } + +- PyThreadState *tstate = _PyThreadState_GET(); ++ tstate = _PyThreadState_GET(); + #ifdef Py_DEBUG + // bpo-40839: Before Python 3.10, it was possible to call PyDict_GetItem() + // with the GIL released. +@@ -1673,9 +1767,6 @@ PyDict_GetItem(PyObject *op, PyObject *key) + #endif + + /* Preserve the existing exception */ +- PyObject *exc_type, *exc_value, *exc_tb; +- PyObject *value; +- Py_ssize_t ix; (void)ix; + + _PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb); + ix = _Py_dict_lookup(mp, key, hash, &value); +@@ -1692,6 +1783,8 @@ Py_ssize_t + _PyDict_GetItemHint(PyDictObject *mp, PyObject *key, + Py_ssize_t hint, PyObject **value) + { ++ Py_hash_t hash; ++ + assert(*value == NULL); + assert(PyDict_CheckExact((PyObject*)mp)); + assert(PyUnicode_CheckExact(key)); +@@ -1733,7 +1826,7 @@ _PyDict_GetItemHint(PyDictObject *mp, PyObject *key, + } + } + +- Py_hash_t hash = unicode_get_hash(key); ++ hash = unicode_get_hash(key); + if (hash == -1) { + hash = PyObject_Hash(key); + if (hash == -1) { +@@ -1751,10 +1844,11 @@ _PyDict_GetItemHint(PyDictObject *mp, PyObject *key, + PyObject * + _PyDict_GetItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash) + { +- Py_ssize_t ix; (void)ix; +- PyDictObject *mp = (PyDictObject *)op; ++ Py_ssize_t ix; ++ PyDictObject *mp; + PyObject *value; + ++ mp = (PyDictObject *)op; + if (!PyDict_Check(op)) { + PyErr_BadInternalCall(); + return NULL; +@@ -1772,7 +1866,7 @@ _PyDict_GetItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash) + PyObject * + PyDict_GetItemWithError(PyObject *op, PyObject *key) + { +- Py_ssize_t ix; (void)ix; ++ Py_ssize_t ix; + Py_hash_t hash; + PyDictObject*mp = (PyDictObject *)op; + PyObject *value; +@@ -1797,8 +1891,10 @@ PyDict_GetItemWithError(PyObject *op, PyObject *key) + PyObject * + _PyDict_GetItemWithError(PyObject *dp, PyObject *kv) + { ++ Py_hash_t hash; ++ + assert(PyUnicode_CheckExact(kv)); +- Py_hash_t hash = kv->ob_type->tp_hash(kv); ++ hash = kv->ob_type->tp_hash(kv); + if (hash == -1) { + return NULL; + } +@@ -1809,10 +1905,12 @@ PyObject * + _PyDict_GetItemIdWithError(PyObject *dp, _Py_Identifier *key) + { + PyObject *kv; ++ Py_hash_t hash; ++ + kv = _PyUnicode_FromId(key); /* borrowed */ + if (kv == NULL) + return NULL; +- Py_hash_t hash = unicode_get_hash(kv); ++ hash = unicode_get_hash(kv); + assert (hash != -1); /* interned strings have their hash value initialised */ + return _PyDict_GetItem_KnownHash(dp, kv, hash); + } +@@ -1870,10 +1968,11 @@ _PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key) + int + _PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value) + { ++ Py_hash_t hash; ++ + assert(key); + assert(value); + assert(PyDict_Check(mp)); +- Py_hash_t hash; + if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) { + hash = PyObject_Hash(key); + if (hash == -1) { +@@ -2126,6 +2225,7 @@ _PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, + PyDictObject *mp; + PyObject *key, *value; + Py_hash_t hash; ++ int index; + + if (!PyDict_Check(op)) + return 0; +@@ -2135,7 +2235,7 @@ _PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, + assert(mp->ma_used <= SHARED_KEYS_MAX_SIZE); + if (i < 0 || i >= mp->ma_used) + return 0; +- int index = get_index_from_order(mp, i); ++ index = get_index_from_order(mp, i); + value = mp->ma_values->values[index]; + + key = DK_UNICODE_ENTRIES(mp->ma_keys)[index].me_key; +@@ -2365,6 +2465,9 @@ dict_dealloc(PyDictObject *mp) + PyDictValues *values = mp->ma_values; + PyDictKeysObject *keys = mp->ma_keys; + Py_ssize_t i, n; ++#if PyDict_MAXFREELIST > 0 ++ struct _Py_dict_state *state; ++#endif + + /* bpo-31095: UnTrack is needed before calling any callbacks */ + PyObject_GC_UnTrack(mp); +@@ -2381,7 +2484,7 @@ dict_dealloc(PyDictObject *mp) + dictkeys_decref(keys); + } + #if PyDict_MAXFREELIST > 0 +- struct _Py_dict_state *state = get_dict_state(); ++ state = get_dict_state(); + #ifdef Py_DEBUG + // new_dict() must not be called after _PyDict_Fini() + assert(state->numfree != -1); +@@ -2544,6 +2647,8 @@ dict_keys(PyDictObject *mp) + { + PyObject *v; + Py_ssize_t n; ++ Py_ssize_t j, pos; ++ PyObject *key; + + again: + n = mp->ma_used; +@@ -2559,8 +2664,8 @@ dict_keys(PyDictObject *mp) + } + + /* Nothing we do below makes any function calls. */ +- Py_ssize_t j = 0, pos = 0; +- PyObject *key; ++ j = 0; ++ pos = 0; + while (_PyDict_Next((PyObject*)mp, &pos, &key, NULL, NULL)) { + assert(j < n); + Py_INCREF(key); +@@ -2575,7 +2680,9 @@ static PyObject * + dict_values(PyDictObject *mp) + { + PyObject *v; ++ PyObject *value; + Py_ssize_t n; ++ Py_ssize_t j, pos; + + again: + n = mp->ma_used; +@@ -2591,8 +2698,8 @@ dict_values(PyDictObject *mp) + } + + /* Nothing we do below makes any function calls. */ +- Py_ssize_t j = 0, pos = 0; +- PyObject *value; ++ j = 0; ++ pos = 0; + while (_PyDict_Next((PyObject*)mp, &pos, NULL, &value, NULL)) { + assert(j < n); + Py_INCREF(value); +@@ -2609,6 +2716,8 @@ dict_items(PyDictObject *mp) + PyObject *v; + Py_ssize_t i, n; + PyObject *item; ++ Py_ssize_t j, pos; ++ PyObject *key, *value; + + /* Preallocate the list of tuples, to avoid allocations during + * the loop over the items, which could trigger GC, which +@@ -2636,11 +2745,11 @@ dict_items(PyDictObject *mp) + } + + /* Nothing we do below makes any function calls. */ +- Py_ssize_t j = 0, pos = 0; +- PyObject *key, *value; ++ j = 0; ++ pos = 0; + while (_PyDict_Next((PyObject*)mp, &pos, &key, &value, NULL)) { + assert(j < n); +- PyObject *item = PyList_GET_ITEM(v, j); ++ item = PyList_GET_ITEM(v, j); + Py_INCREF(key); + PyTuple_SET_ITEM(item, 0, key); + Py_INCREF(value); +@@ -2672,10 +2781,11 @@ dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value) + static int + dict_update_arg(PyObject *self, PyObject *arg) + { ++ PyObject *func; ++ + if (PyDict_CheckExact(arg)) { + return PyDict_Merge(self, arg, 1); + } +- PyObject *func; + if (_PyObject_LookupAttr(arg, &_Py_ID(keys), &func) < 0) { + return -1; + } +@@ -2819,6 +2929,10 @@ static int + dict_merge(PyObject *a, PyObject *b, int override) + { + PyDictObject *mp, *other; ++ PyDictKeysObject *okeys; ++ Py_ssize_t orig_size, pos; ++ Py_hash_t hash; ++ PyObject *key, *value; + + assert(0 <= override && override <= 2); + +@@ -2843,7 +2957,7 @@ dict_merge(PyObject *a, PyObject *b, int override) + * skips the unnecessary test. + */ + override = 1; +- PyDictKeysObject *okeys = other->ma_keys; ++ okeys = other->ma_keys; + + // If other is clean, combined, and just allocated, just clone it. + if (other->ma_values == NULL && +@@ -2885,10 +2999,8 @@ dict_merge(PyObject *a, PyObject *b, int override) + } + } + +- Py_ssize_t orig_size = other->ma_keys->dk_nentries; +- Py_ssize_t pos = 0; +- Py_hash_t hash; +- PyObject *key, *value; ++ orig_size = other->ma_keys->dk_nentries; ++ pos = 0; + + while (_PyDict_Next((PyObject*)other, &pos, &key, &value, &hash)) { + int err = 0; +@@ -3017,7 +3129,12 @@ PyDict_Copy(PyObject *o) + { + PyObject *copy; + PyDictObject *mp; +- Py_ssize_t i, n; ++ PyDictObject *split_copy; ++ PyDictObject *new; ++ PyDictKeysObject *keys; ++ PyDictValues *newvalues; ++ Py_ssize_t i, n, size; ++ size_t prefix_size; + + if (o == NULL || !PyDict_Check(o)) { + PyErr_BadInternalCall(); +@@ -3031,9 +3148,7 @@ PyDict_Copy(PyObject *o) + } + + if (_PyDict_HasSplitTable(mp)) { +- PyDictObject *split_copy; +- Py_ssize_t size = shared_keys_usable_size(mp->ma_keys); +- PyDictValues *newvalues; ++ size = shared_keys_usable_size(mp->ma_keys); + newvalues = new_values(size); + if (newvalues == NULL) + return PyErr_NoMemory(); +@@ -3042,7 +3157,7 @@ PyDict_Copy(PyObject *o) + free_values(newvalues); + return NULL; + } +- size_t prefix_size = ((uint8_t *)newvalues)[-1]; ++ prefix_size = ((uint8_t *)newvalues)[-1]; + memcpy(((char *)newvalues)-prefix_size, ((char *)mp->ma_values)-prefix_size, prefix_size-1); + split_copy->ma_values = newvalues; + split_copy->ma_keys = mp->ma_keys; +@@ -3077,11 +3192,11 @@ PyDict_Copy(PyObject *o) + operations and copied after that. In cases like this, we defer to + PyDict_Merge, which produces a compacted copy. + */ +- PyDictKeysObject *keys = clone_combined_dict_keys(mp); ++ keys = clone_combined_dict_keys(mp); + if (keys == NULL) { + return NULL; + } +- PyDictObject *new = (PyDictObject *)new_dict(keys, NULL, 0, 0); ++ new = (PyDictObject *)new_dict(keys, NULL, 0, 0); + if (new == NULL) { + /* In case of an error, `new_dict()` takes care of + cleaning up `keys`. */ +@@ -3300,9 +3415,14 @@ dict_get_impl(PyDictObject *self, PyObject *key, PyObject *default_value) + PyObject * + PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj) + { +- PyDictObject *mp = (PyDictObject *)d; ++ PyDictObject *mp; + PyObject *value; + Py_hash_t hash; ++ Py_ssize_t ix, hashpos, index; ++ PyDictUnicodeEntry *unicode_ep; ++ PyDictKeyEntry *key_ep; ++ ++ mp = (PyDictObject *)d; + + if (!PyDict_Check(d)) { + PyErr_BadInternalCall(); +@@ -3330,7 +3450,7 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj) + } + } + +- Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &value); ++ ix = _Py_dict_lookup(mp, key, hash, &value); + if (ix == DKIX_ERROR) + return NULL; + +@@ -3342,28 +3462,28 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj) + return NULL; + } + } +- Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash); ++ hashpos = find_empty_slot(mp->ma_keys, hash); + dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries); + if (DK_IS_UNICODE(mp->ma_keys)) { + assert(PyUnicode_CheckExact(key)); +- PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries]; +- ep->me_key = key; ++ unicode_ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries]; ++ unicode_ep->me_key = key; + if (_PyDict_HasSplitTable(mp)) { +- Py_ssize_t index = (int)mp->ma_keys->dk_nentries; ++ index = (int)mp->ma_keys->dk_nentries; + assert(index < SHARED_KEYS_MAX_SIZE); + assert(mp->ma_values->values[index] == NULL); + mp->ma_values->values[index] = value; + _PyDictValues_AddToInsertionOrder(mp->ma_values, index); + } + else { +- ep->me_value = value; ++ unicode_ep->me_value = value; + } + } + else { +- PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries]; +- ep->me_key = key; +- ep->me_hash = hash; +- ep->me_value = value; ++ key_ep = &DK_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries]; ++ key_ep->me_key = key; ++ key_ep->me_hash = hash; ++ key_ep->me_value = value; + } + Py_INCREF(key); + Py_INCREF(value); +@@ -3456,6 +3576,8 @@ dict_popitem_impl(PyDictObject *self) + { + Py_ssize_t i, j; + PyObject *res; ++ PyObject *key, *value; ++ Py_hash_t hash; + + /* Allocate the result tuple before checking the size. Believe it + * or not, this allocation could trigger a garbage collection which +@@ -3484,8 +3606,6 @@ dict_popitem_impl(PyDictObject *self) + self->ma_keys->dk_version = 0; + + /* Pop last item */ +- PyObject *key, *value; +- Py_hash_t hash; + if (DK_IS_UNICODE(self->ma_keys)) { + PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(self->ma_keys); + i = self->ma_keys->dk_nentries - 1; +@@ -3608,10 +3728,12 @@ dict_sizeof(PyDictObject *mp, PyObject *Py_UNUSED(ignored)) + static PyObject * + dict_or(PyObject *self, PyObject *other) + { ++ PyObject *new; ++ + if (!PyDict_Check(self) || !PyDict_Check(other)) { + Py_RETURN_NOTIMPLEMENTED; + } +- PyObject *new = PyDict_Copy(self); ++ new = PyDict_Copy(self); + if (new == NULL) { + return NULL; + } +@@ -3747,24 +3869,46 @@ static PySequenceMethods dict_as_sequence = { + 0, /* sq_inplace_repeat */ + }; + ++static PyObject *dict_vectorcall(PyObject *type, PyObject * const*args, ++ size_t nargsf, PyObject *kwnames); ++#if defined(MS_WINDOWS) && defined(_MSC_VER) && _MSC_VER < 1300 ++static void _PyDict_InitViewTypes(void); ++#endif ++ ++#if !defined(MS_WINDOWS) || !defined(_MSC_VER) || _MSC_VER >= 1300 + static PyNumberMethods dict_as_number = { + .nb_or = dict_or, + .nb_inplace_or = dict_ior, + }; ++#else ++static PyNumberMethods dict_as_number = {0}; ++ ++void ++_PyDict_InitTypes(void) ++{ ++ dict_as_number.nb_or = dict_or; ++ dict_as_number.nb_inplace_or = dict_ior; ++ PyDict_Type.tp_vectorcall = dict_vectorcall; ++ _PyDict_InitViewTypes(); ++} ++#endif + + static PyObject * + dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + { ++ PyObject *self; ++ PyDictObject *d; ++ + assert(type != NULL); + assert(type->tp_alloc != NULL); + // dict subclasses must implement the GC protocol + assert(_PyType_IS_GC(type)); + +- PyObject *self = type->tp_alloc(type, 0); ++ self = type->tp_alloc(type, 0); + if (self == NULL) { + return NULL; + } +- PyDictObject *d = (PyDictObject *)self; ++ d = (PyDictObject *)self; + + d->ma_used = 0; + d->ma_version_tag = DICT_NEXT_VERSION(); +@@ -3797,11 +3941,14 @@ dict_vectorcall(PyObject *type, PyObject * const*args, + size_t nargsf, PyObject *kwnames) + { + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); ++ Py_ssize_t i; ++ PyObject *self; ++ + if (!_PyArg_CheckPositional("dict", nargs, 0, 1)) { + return NULL; + } + +- PyObject *self = dict_new(_PyType_CAST(type), NULL, NULL); ++ self = dict_new(_PyType_CAST(type), NULL, NULL); + if (self == NULL) { + return NULL; + } +@@ -3813,7 +3960,7 @@ dict_vectorcall(PyObject *type, PyObject * const*args, + args++; + } + if (kwnames != NULL) { +- for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(kwnames); i++) { ++ for (i = 0; i < PyTuple_GET_SIZE(kwnames); i++) { + if (PyDict_SetItem(self, PyTuple_GET_ITEM(kwnames, i), args[i]) < 0) { + Py_DECREF(self); + return NULL; +@@ -3882,7 +4029,9 @@ PyTypeObject PyDict_Type = { + _PyType_AllocNoTrack, /* tp_alloc */ + dict_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ ++#if !defined(MS_WINDOWS) || !defined(_MSC_VER) || _MSC_VER >= 1300 + .tp_vectorcall = dict_vectorcall, ++#endif + }; + + /* For backward compatibility with old dictionary interface */ +@@ -4048,6 +4197,7 @@ dictiter_iternextkey(dictiterobject *di) + Py_ssize_t i; + PyDictKeysObject *k; + PyDictObject *d = di->di_dict; ++ int index; + + if (d == NULL) + return NULL; +@@ -4066,7 +4216,7 @@ dictiter_iternextkey(dictiterobject *di) + if (d->ma_values) { + if (i >= d->ma_used) + goto fail; +- int index = get_index_from_order(d, i); ++ index = get_index_from_order(d, i); + key = DK_UNICODE_ENTRIES(k)[index].me_key; + assert(d->ma_values->values[index] != NULL); + } +@@ -4148,6 +4298,7 @@ dictiter_iternextvalue(dictiterobject *di) + { + PyObject *value; + Py_ssize_t i; ++ int index; + PyDictObject *d = di->di_dict; + + if (d == NULL) +@@ -4166,7 +4317,7 @@ dictiter_iternextvalue(dictiterobject *di) + if (d->ma_values) { + if (i >= d->ma_used) + goto fail; +- int index = get_index_from_order(d, i); ++ index = get_index_from_order(d, i); + value = d->ma_values->values[index]; + assert(value != NULL); + } +@@ -4248,6 +4399,7 @@ dictiter_iternextitem(dictiterobject *di) + { + PyObject *key, *value, *result; + Py_ssize_t i; ++ int index; + PyDictObject *d = di->di_dict; + + if (d == NULL) +@@ -4266,7 +4418,7 @@ dictiter_iternextitem(dictiterobject *di) + if (d->ma_values) { + if (i >= d->ma_used) + goto fail; +- int index = get_index_from_order(d, i); ++ index = get_index_from_order(d, i); + key = DK_UNICODE_ENTRIES(d->ma_keys)[index].me_key; + value = d->ma_values->values[index]; + assert(value != NULL); +@@ -4375,6 +4527,10 @@ PyTypeObject PyDictIterItem_Type = { + static PyObject * + dictreviter_iternext(dictiterobject *di) + { ++ Py_ssize_t i; ++ PyDictKeysObject *k; ++ PyObject *key, *value, *result; ++ int index; + PyDictObject *d = di->di_dict; + + if (d == NULL) { +@@ -4389,15 +4545,14 @@ dictreviter_iternext(dictiterobject *di) + return NULL; + } + +- Py_ssize_t i = di->di_pos; +- PyDictKeysObject *k = d->ma_keys; +- PyObject *key, *value, *result; ++ i = di->di_pos; ++ k = d->ma_keys; + + if (i < 0) { + goto fail; + } + if (d->ma_values) { +- int index = get_index_from_order(d, i); ++ index = get_index_from_order(d, i); + key = DK_UNICODE_ENTRIES(k)[index].me_key; + value = d->ma_values->values[index]; + assert (value != NULL); +@@ -4479,12 +4634,32 @@ PyTypeObject PyDictRevIterKey_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "dict_reversekeyiterator", + sizeof(dictiterobject), +- .tp_dealloc = (destructor)dictiter_dealloc, +- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, +- .tp_traverse = (traverseproc)dictiter_traverse, +- .tp_iter = PyObject_SelfIter, +- .tp_iternext = (iternextfunc)dictreviter_iternext, +- .tp_methods = dictiter_methods ++ 0, ++ (destructor)dictiter_dealloc, ++ 0, ++ 0, ++ 0, ++ 0, ++ 0, ++ 0, ++ 0, ++ 0, ++ 0, ++ 0, ++ 0, ++ PyObject_GenericGetAttr, ++ 0, ++ 0, ++ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, ++ 0, ++ (traverseproc)dictiter_traverse, ++ 0, ++ 0, ++ 0, ++ PyObject_SelfIter, ++ (iternextfunc)dictreviter_iternext, ++ dictiter_methods, ++ 0, + }; + + +@@ -4505,11 +4680,14 @@ dict___reversed___impl(PyDictObject *self) + static PyObject * + dictiter_reduce(dictiterobject *di, PyObject *Py_UNUSED(ignored)) + { ++ dictiterobject tmp; ++ PyObject *list; ++ + /* copy the iterator state */ +- dictiterobject tmp = *di; ++ tmp = *di; + Py_XINCREF(tmp.di_dict); + +- PyObject *list = PySequence_List((PyObject*)&tmp); ++ list = PySequence_List((PyObject*)&tmp); + Py_XDECREF(tmp.di_dict); + if (list == NULL) { + return NULL; +@@ -4521,24 +4699,40 @@ PyTypeObject PyDictRevIterItem_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "dict_reverseitemiterator", + sizeof(dictiterobject), +- .tp_dealloc = (destructor)dictiter_dealloc, +- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, +- .tp_traverse = (traverseproc)dictiter_traverse, +- .tp_iter = PyObject_SelfIter, +- .tp_iternext = (iternextfunc)dictreviter_iternext, +- .tp_methods = dictiter_methods ++ 0, ++ (destructor)dictiter_dealloc, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ PyObject_GenericGetAttr, ++ 0, ++ 0, ++ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, ++ 0, ++ (traverseproc)dictiter_traverse, ++ 0, 0, 0, ++ PyObject_SelfIter, ++ (iternextfunc)dictreviter_iternext, ++ dictiter_methods, ++ 0, + }; + + PyTypeObject PyDictRevIterValue_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "dict_reversevalueiterator", + sizeof(dictiterobject), +- .tp_dealloc = (destructor)dictiter_dealloc, +- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, +- .tp_traverse = (traverseproc)dictiter_traverse, +- .tp_iter = PyObject_SelfIter, +- .tp_iternext = (iternextfunc)dictreviter_iternext, +- .tp_methods = dictiter_methods ++ 0, ++ (destructor)dictiter_dealloc, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ PyObject_GenericGetAttr, ++ 0, ++ 0, ++ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, ++ 0, ++ (traverseproc)dictiter_traverse, ++ 0, 0, 0, ++ PyObject_SelfIter, ++ (iternextfunc)dictreviter_iternext, ++ dictiter_methods, ++ 0, + }; + + /***********************************************/ +@@ -4598,11 +4792,13 @@ _PyDictView_New(PyObject *dict, PyTypeObject *type) + + static PyObject * + dictview_mapping(PyObject *view, void *Py_UNUSED(ignored)) { ++ PyObject *mapping; ++ + assert(view != NULL); + assert(PyDictKeys_Check(view) + || PyDictValues_Check(view) + || PyDictItems_Check(view)); +- PyObject *mapping = (PyObject *)((_PyDictViewObject *)view)->dv_dict; ++ mapping = (PyObject *)((_PyDictViewObject *)view)->dv_dict; + return PyDictProxy_New(mapping); + } + +@@ -4612,6 +4808,16 @@ static PyGetSetDef dictview_getset[] = { + {0} + }; + ++#if defined(MS_WINDOWS) && defined(_MSC_VER) && _MSC_VER < 1300 ++static void ++_PyDict_InitViewTypes(void) ++{ ++ PyDictKeys_Type.tp_getset = dictview_getset; ++ PyDictItems_Type.tp_getset = dictview_getset; ++ PyDictValues_Type.tp_getset = dictview_getset; ++} ++#endif ++ + /* TODO(guido): The views objects are not complete: + + * support more set operations +@@ -4779,12 +4985,15 @@ dictviews_to_set(PyObject *self) + static PyObject* + dictviews_sub(PyObject *self, PyObject *other) + { +- PyObject *result = dictviews_to_set(self); ++ PyObject *result; ++ PyObject *tmp; ++ ++ result = dictviews_to_set(self); + if (result == NULL) { + return NULL; + } + +- PyObject *tmp = PyObject_CallMethodOneArg( ++ tmp = PyObject_CallMethodOneArg( + result, &_Py_ID(difference_update), other); + if (tmp == NULL) { + Py_DECREF(result); +@@ -4901,31 +5110,38 @@ dictviews_or(PyObject* self, PyObject *other) + static PyObject * + dictitems_xor(PyObject *self, PyObject *other) + { ++ PyObject *d1, *d2, *temp_dict, *result_set; ++ PyObject *key, *val1, *val2, *remaining_pairs; ++ Py_ssize_t pos; ++ Py_hash_t hash; ++ int to_delete; ++ + assert(PyDictItems_Check(self)); + assert(PyDictItems_Check(other)); +- PyObject *d1 = (PyObject *)((_PyDictViewObject *)self)->dv_dict; +- PyObject *d2 = (PyObject *)((_PyDictViewObject *)other)->dv_dict; ++ d1 = (PyObject *)((_PyDictViewObject *)self)->dv_dict; ++ d2 = (PyObject *)((_PyDictViewObject *)other)->dv_dict; + +- PyObject *temp_dict = PyDict_Copy(d1); ++ temp_dict = PyDict_Copy(d1); + if (temp_dict == NULL) { + return NULL; + } +- PyObject *result_set = PySet_New(NULL); ++ result_set = PySet_New(NULL); + if (result_set == NULL) { + Py_CLEAR(temp_dict); + return NULL; + } + +- PyObject *key = NULL, *val1 = NULL, *val2 = NULL; +- Py_ssize_t pos = 0; +- Py_hash_t hash; ++ key = NULL; ++ val1 = NULL; ++ val2 = NULL; ++ pos = 0; + + while (_PyDict_Next(d2, &pos, &key, &val2, &hash)) { + Py_INCREF(key); + Py_INCREF(val2); + val1 = _PyDict_GetItem_KnownHash(temp_dict, key, hash); + +- int to_delete; ++ to_delete = 0; + if (val1 == NULL) { + if (PyErr_Occurred()) { + goto error; +@@ -4962,7 +5178,7 @@ dictitems_xor(PyObject *self, PyObject *other) + } + key = val1 = val2 = NULL; + +- PyObject *remaining_pairs = PyObject_CallMethodNoArgs( ++ remaining_pairs = PyObject_CallMethodNoArgs( + temp_dict, &_Py_ID(items)); + if (remaining_pairs == NULL) { + goto error; +@@ -4987,15 +5203,18 @@ dictitems_xor(PyObject *self, PyObject *other) + static PyObject* + dictviews_xor(PyObject* self, PyObject *other) + { ++ PyObject *result; ++ PyObject *tmp; ++ + if (PyDictItems_Check(self) && PyDictItems_Check(other)) { + return dictitems_xor(self, other); + } +- PyObject *result = dictviews_to_set(self); ++ result = dictviews_to_set(self); + if (result == NULL) { + return NULL; + } + +- PyObject *tmp = PyObject_CallMethodOneArg( ++ tmp = PyObject_CallMethodOneArg( + result, &_Py_ID(symmetric_difference_update), other); + if (tmp == NULL) { + Py_DECREF(result); +@@ -5122,7 +5341,9 @@ PyTypeObject PyDictKeys_Type = { + (getiterfunc)dictkeys_iter, /* tp_iter */ + 0, /* tp_iternext */ + dictkeys_methods, /* tp_methods */ ++#if !defined(MS_WINDOWS) || !defined(_MSC_VER) || _MSC_VER >= 1300 + .tp_getset = dictview_getset, ++#endif + }; + + static PyObject * +@@ -5228,7 +5449,9 @@ PyTypeObject PyDictItems_Type = { + (getiterfunc)dictitems_iter, /* tp_iter */ + 0, /* tp_iternext */ + dictitems_methods, /* tp_methods */ ++#if !defined(MS_WINDOWS) || !defined(_MSC_VER) || _MSC_VER >= 1300 + .tp_getset = dictview_getset, ++#endif + }; + + static PyObject * +@@ -5309,7 +5532,9 @@ PyTypeObject PyDictValues_Type = { + (getiterfunc)dictvalues_iter, /* tp_iter */ + 0, /* tp_iternext */ + dictvalues_methods, /* tp_methods */ ++#if !defined(MS_WINDOWS) || !defined(_MSC_VER) || _MSC_VER >= 1300 + .tp_getset = dictview_getset, ++#endif + }; + + static PyObject * +@@ -5351,24 +5576,29 @@ _PyDict_NewKeysForClass(void) + static int + init_inline_values(PyObject *obj, PyTypeObject *tp) + { ++ PyDictKeysObject *keys; ++ Py_ssize_t size; ++ PyDictValues *values; ++ int i; ++ + assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE); + // assert(type->tp_dictoffset > 0); -- TO DO Update this assert. + assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); +- PyDictKeysObject *keys = CACHED_KEYS(tp); ++ keys = CACHED_KEYS(tp); + assert(keys != NULL); + if (keys->dk_usable > 1) { + keys->dk_usable--; + } +- Py_ssize_t size = shared_keys_usable_size(keys); ++ size = shared_keys_usable_size(keys); + assert(size > 0); +- PyDictValues *values = new_values(size); ++ values = new_values(size); + if (values == NULL) { + PyErr_NoMemory(); + return -1; + } + assert(((uint8_t *)values)[-1] >= size+2); + ((uint8_t *)values)[-2] = 0; +- for (int i = 0; i < size; i++) { ++ for (i = 0; i < size; i++) { + values->values[i] = NULL; + } + *_PyObject_ValuesPointer(obj) = values; +@@ -5378,7 +5608,11 @@ init_inline_values(PyObject *obj, PyTypeObject *tp) + int + _PyObject_InitializeDict(PyObject *obj) + { +- PyTypeObject *tp = Py_TYPE(obj); ++ PyTypeObject *tp; ++ PyObject *dict; ++ PyObject **dictptr; ++ ++ tp = Py_TYPE(obj); + if (tp->tp_dictoffset == 0) { + return 0; + } +@@ -5386,7 +5620,6 @@ _PyObject_InitializeDict(PyObject *obj) + OBJECT_STAT_INC(new_values); + return init_inline_values(obj, tp); + } +- PyObject *dict; + if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) { + dictkeys_incref(CACHED_KEYS(tp)); + dict = new_dict_with_shared_keys(CACHED_KEYS(tp)); +@@ -5397,7 +5630,7 @@ _PyObject_InitializeDict(PyObject *obj) + if (dict == NULL) { + return -1; + } +- PyObject **dictptr = _PyObject_DictPointer(obj); ++ dictptr = _PyObject_DictPointer(obj); + *dictptr = dict; + return 0; + } +@@ -5405,17 +5638,20 @@ _PyObject_InitializeDict(PyObject *obj) + static PyObject * + make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values) + { ++ Py_ssize_t used, track, i; ++ PyObject *val, *res; ++ + dictkeys_incref(keys); +- Py_ssize_t used = 0; +- Py_ssize_t track = 0; +- for (Py_ssize_t i = 0; i < shared_keys_usable_size(keys); i++) { +- PyObject *val = values->values[i]; ++ used = 0; ++ track = 0; ++ for (i = 0; i < shared_keys_usable_size(keys); i++) { ++ val = values->values[i]; + if (val != NULL) { + used += 1; + track += _PyObject_GC_MAY_BE_TRACKED(val); + } + } +- PyObject *res = new_dict(keys, values, used, 0); ++ res = new_dict(keys, values, used, 0); + if (track && res) { + _PyObject_GC_TRACK(res); + } +@@ -5425,8 +5661,10 @@ make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values) + PyObject * + _PyObject_MakeDictFromInstanceAttributes(PyObject *obj, PyDictValues *values) + { ++ PyDictKeysObject *keys; ++ + assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT); +- PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj)); ++ keys = CACHED_KEYS(Py_TYPE(obj)); + OBJECT_STAT_INC(dict_materialized_on_request); + return make_dict_from_instance_attributes(keys, values); + } +@@ -5435,11 +5673,15 @@ int + _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, + PyObject *name, PyObject *value) + { +- PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj)); ++ PyDictKeysObject *keys; ++ Py_ssize_t ix; ++ PyObject *dict, *old_value; ++ ++ keys = CACHED_KEYS(Py_TYPE(obj)); + assert(keys != NULL); + assert(values != NULL); + assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT); +- Py_ssize_t ix = DKIX_EMPTY; ++ ix = DKIX_EMPTY; + if (PyUnicode_CheckExact(name)) { + ix = insert_into_dictkeys(keys, name); + } +@@ -5457,7 +5699,7 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, + OBJECT_STAT_INC(dict_materialized_str_subclass); + } + #endif +- PyObject *dict = make_dict_from_instance_attributes(keys, values); ++ dict = make_dict_from_instance_attributes(keys, values); + if (dict == NULL) { + return -1; + } +@@ -5470,7 +5712,7 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, + return PyDict_SetItem(dict, name, value); + } + } +- PyObject *old_value = values->values[ix]; ++ old_value = values->values[ix]; + Py_XINCREF(value); + values->values[ix] = value; + if (old_value == NULL) { +@@ -5495,14 +5737,18 @@ PyObject * + _PyObject_GetInstanceAttribute(PyObject *obj, PyDictValues *values, + PyObject *name) + { ++ PyDictKeysObject *keys; ++ Py_ssize_t ix; ++ PyObject *value; ++ + assert(PyUnicode_CheckExact(name)); +- PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj)); ++ keys = CACHED_KEYS(Py_TYPE(obj)); + assert(keys != NULL); +- Py_ssize_t ix = _PyDictKeys_StringLookup(keys, name); ++ ix = _PyDictKeys_StringLookup(keys, name); + if (ix == DKIX_EMPTY) { + return NULL; + } +- PyObject *value = values->values[ix]; ++ value = values->values[ix]; + Py_XINCREF(value); + return value; + } +@@ -5510,16 +5756,22 @@ _PyObject_GetInstanceAttribute(PyObject *obj, PyDictValues *values, + int + _PyObject_IsInstanceDictEmpty(PyObject *obj) + { +- PyTypeObject *tp = Py_TYPE(obj); ++ PyTypeObject *tp; ++ PyObject **dictptr; ++ PyObject *dict; ++ PyDictValues *values; ++ PyDictKeysObject *keys; ++ Py_ssize_t i; ++ ++ tp = Py_TYPE(obj); + if (tp->tp_dictoffset == 0) { + return 1; + } +- PyObject **dictptr; + if (tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) { +- PyDictValues *values = *_PyObject_ValuesPointer(obj); ++ values = *_PyObject_ValuesPointer(obj); + if (values) { +- PyDictKeysObject *keys = CACHED_KEYS(tp); +- for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) { ++ keys = CACHED_KEYS(tp); ++ for (i = 0; i < keys->dk_nentries; i++) { + if (values->values[i] != NULL) { + return 0; + } +@@ -5531,7 +5783,7 @@ _PyObject_IsInstanceDictEmpty(PyObject *obj) + else { + dictptr = _PyObject_DictPointer(obj); + } +- PyObject *dict = *dictptr; ++ dict = *dictptr; + if (dict == NULL) { + return 1; + } +@@ -5542,14 +5794,19 @@ _PyObject_IsInstanceDictEmpty(PyObject *obj) + int + _PyObject_VisitInstanceAttributes(PyObject *self, visitproc visit, void *arg) + { +- PyTypeObject *tp = Py_TYPE(self); ++ PyTypeObject *tp; ++ PyDictValues **values_ptr; ++ PyDictKeysObject *keys; ++ Py_ssize_t i; ++ ++ tp = Py_TYPE(self); + assert(Py_TYPE(self)->tp_flags & Py_TPFLAGS_MANAGED_DICT); +- PyDictValues **values_ptr = _PyObject_ValuesPointer(self); ++ values_ptr = _PyObject_ValuesPointer(self); + if (*values_ptr == NULL) { + return 0; + } +- PyDictKeysObject *keys = CACHED_KEYS(tp); +- for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) { ++ keys = CACHED_KEYS(tp); ++ for (i = 0; i < keys->dk_nentries; i++) { + Py_VISIT((*values_ptr)->values[i]); + } + return 0; +@@ -5558,14 +5815,19 @@ _PyObject_VisitInstanceAttributes(PyObject *self, visitproc visit, void *arg) + void + _PyObject_ClearInstanceAttributes(PyObject *self) + { +- PyTypeObject *tp = Py_TYPE(self); ++ PyTypeObject *tp; ++ PyDictValues **values_ptr; ++ PyDictKeysObject *keys; ++ Py_ssize_t i; ++ ++ tp = Py_TYPE(self); + assert(Py_TYPE(self)->tp_flags & Py_TPFLAGS_MANAGED_DICT); +- PyDictValues **values_ptr = _PyObject_ValuesPointer(self); ++ values_ptr = _PyObject_ValuesPointer(self); + if (*values_ptr == NULL) { + return; + } +- PyDictKeysObject *keys = CACHED_KEYS(tp); +- for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) { ++ keys = CACHED_KEYS(tp); ++ for (i = 0; i < keys->dk_nentries; i++) { + Py_CLEAR((*values_ptr)->values[i]); + } + } +@@ -5573,16 +5835,22 @@ _PyObject_ClearInstanceAttributes(PyObject *self) + void + _PyObject_FreeInstanceAttributes(PyObject *self) + { +- PyTypeObject *tp = Py_TYPE(self); ++ PyTypeObject *tp; ++ PyDictValues **values_ptr; ++ PyDictValues *values; ++ PyDictKeysObject *keys; ++ Py_ssize_t i; ++ ++ tp = Py_TYPE(self); + assert(Py_TYPE(self)->tp_flags & Py_TPFLAGS_MANAGED_DICT); +- PyDictValues **values_ptr = _PyObject_ValuesPointer(self); +- PyDictValues *values = *values_ptr; ++ values_ptr = _PyObject_ValuesPointer(self); ++ values = *values_ptr; + if (values == NULL) { + return; + } + *values_ptr = NULL; +- PyDictKeysObject *keys = CACHED_KEYS(tp); +- for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) { ++ keys = CACHED_KEYS(tp); ++ for (i = 0; i < keys->dk_nentries; i++) { + Py_XDECREF(values->values[i]); + } + free_values(values); +@@ -5687,13 +5955,15 @@ static uint32_t next_dict_keys_version = 2; + + uint32_t _PyDictKeys_GetVersionForCurrentState(PyDictKeysObject *dictkeys) + { ++ uint32_t v; ++ + if (dictkeys->dk_version != 0) { + return dictkeys->dk_version; + } + if (next_dict_keys_version == 0) { + return 0; + } +- uint32_t v = next_dict_keys_version++; ++ v = next_dict_keys_version++; + dictkeys->dk_version = v; + return v; + } +diff --git a/Objects/enumobject.c b/Objects/enumobject.c +index d84bac6..718f239 100644 +--- a/Objects/enumobject.c ++++ b/Objects/enumobject.c +@@ -328,7 +328,9 @@ PyTypeObject PyEnum_Type = { + PyType_GenericAlloc, /* tp_alloc */ + enum_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ ++#if !defined(MS_WINDOWS) || !defined(_MSC_VER) || _MSC_VER >= 1300 + .tp_vectorcall = (vectorcallfunc)enumerate_vectorcall ++#endif + }; + + /* Reversed Object ***************************************************************/ +@@ -398,11 +400,13 @@ static PyObject * + reversed_vectorcall(PyObject *type, PyObject * const*args, + size_t nargsf, PyObject *kwnames) + { ++ Py_ssize_t nargs; ++ + if (!_PyArg_NoKwnames("reversed", kwnames)) { + return NULL; + } + +- Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); ++ nargs = PyVectorcall_NARGS(nargsf); + if (!_PyArg_CheckPositional("reversed", nargs, 1, 1)) { + return NULL; + } +@@ -541,5 +545,16 @@ PyTypeObject PyReversed_Type = { + PyType_GenericAlloc, /* tp_alloc */ + reversed_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ ++#if !defined(MS_WINDOWS) || !defined(_MSC_VER) || _MSC_VER >= 1300 + .tp_vectorcall = (vectorcallfunc)reversed_vectorcall, ++#endif + }; ++ ++#if defined(MS_WINDOWS) && defined(_MSC_VER) && _MSC_VER < 1300 ++void ++_PyEnum_InitTypes(void) ++{ ++ PyEnum_Type.tp_vectorcall = (vectorcallfunc)enumerate_vectorcall; ++ PyReversed_Type.tp_vectorcall = (vectorcallfunc)reversed_vectorcall; ++} ++#endif +diff --git a/Objects/exceptions.c b/Objects/exceptions.c +index 86cabbf..59b9c4e 100644 +--- a/Objects/exceptions.c ++++ b/Objects/exceptions.c +@@ -160,6 +160,7 @@ BaseException_setstate(PyObject *self, PyObject *state) + { + PyObject *d_key, *d_value; + Py_ssize_t i = 0; ++ int res; + + if (state != Py_None) { + if (!PyDict_Check(state)) { +@@ -169,7 +170,7 @@ BaseException_setstate(PyObject *self, PyObject *state) + while (PyDict_Next(state, &i, &d_key, &d_value)) { + Py_INCREF(d_key); + Py_INCREF(d_value); +- int res = PyObject_SetAttr(self, d_key, d_value); ++ res = PyObject_SetAttr(self, d_key, d_value); + Py_DECREF(d_value); + Py_DECREF(d_key); + if (res < 0) { +@@ -203,6 +204,8 @@ _PyBaseExceptionObject_cast(PyObject *exc) + static PyObject * + BaseException_add_note(PyObject *self, PyObject *note) + { ++ PyObject *notes; ++ + if (!PyUnicode_Check(note)) { + PyErr_Format(PyExc_TypeError, + "note must be a str, not '%s'", +@@ -210,7 +213,6 @@ BaseException_add_note(PyObject *self, PyObject *note) + return NULL; + } + +- PyObject *notes; + if (_PyObject_LookupAttr(self, &_Py_ID(__notes__), ¬es) < 0) { + return NULL; + } +@@ -698,12 +700,21 @@ _PyBaseExceptionGroupObject_cast(PyObject *exc) + static PyObject * + BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + { +- struct _Py_exc_state *state = get_exc_state(); +- PyTypeObject *PyExc_ExceptionGroup = ++ struct _Py_exc_state *state; ++ PyTypeObject *PyExc_ExceptionGroup; ++ PyObject *message, *exceptions, *exc; ++ Py_ssize_t numexcs, i; ++ bool nested_base_exceptions; ++ int is_nonbase_exception; ++ PyTypeObject *cls; ++ PyBaseExceptionGroupObject *self; ++ ++ state = get_exc_state(); ++ PyExc_ExceptionGroup = + (PyTypeObject*)state->PyExc_ExceptionGroup; + +- PyObject *message = NULL; +- PyObject *exceptions = NULL; ++ message = NULL; ++ exceptions = NULL; + + if (!PyArg_ParseTuple(args, + "UO:BaseExceptionGroup.__new__", +@@ -726,7 +737,7 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + + /* We are now holding a ref to the exceptions tuple */ + +- Py_ssize_t numexcs = PyTuple_GET_SIZE(exceptions); ++ numexcs = PyTuple_GET_SIZE(exceptions); + if (numexcs == 0) { + PyErr_SetString( + PyExc_ValueError, +@@ -734,9 +745,9 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + goto error; + } + +- bool nested_base_exceptions = false; +- for (Py_ssize_t i = 0; i < numexcs; i++) { +- PyObject *exc = PyTuple_GET_ITEM(exceptions, i); ++ nested_base_exceptions = false; ++ for (i = 0; i < numexcs; i++) { ++ exc = PyTuple_GET_ITEM(exceptions, i); + if (!exc) { + goto error; + } +@@ -747,7 +758,7 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + i); + goto error; + } +- int is_nonbase_exception = PyObject_IsInstance(exc, PyExc_Exception); ++ is_nonbase_exception = PyObject_IsInstance(exc, PyExc_Exception); + if (is_nonbase_exception < 0) { + goto error; + } +@@ -756,7 +767,7 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + } + } + +- PyTypeObject *cls = type; ++ cls = type; + if (cls == PyExc_ExceptionGroup) { + if (nested_base_exceptions) { + PyErr_SetString(PyExc_TypeError, +@@ -794,8 +805,7 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + */ + cls = (PyTypeObject*)PyExc_BaseExceptionGroup; + } +- PyBaseExceptionGroupObject *self = +- _PyBaseExceptionGroupObject_cast(BaseException_new(cls, args, kwds)); ++ self = _PyBaseExceptionGroupObject_cast(BaseException_new(cls, args, kwds)); + if (!self) { + goto error; + } +@@ -811,16 +821,18 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + PyObject * + _PyExc_CreateExceptionGroup(const char *msg_str, PyObject *excs) + { +- PyObject *msg = PyUnicode_FromString(msg_str); ++ PyObject *msg, *args, *result; ++ ++ msg = PyUnicode_FromString(msg_str); + if (!msg) { + return NULL; + } +- PyObject *args = PyTuple_Pack(2, msg, excs); ++ args = PyTuple_Pack(2, msg, excs); + Py_DECREF(msg); + if (!args) { + return NULL; + } +- PyObject *result = PyObject_CallObject(PyExc_BaseExceptionGroup, args); ++ result = PyObject_CallObject(PyExc_BaseExceptionGroup, args); + Py_DECREF(args); + return result; + } +@@ -866,11 +878,13 @@ BaseExceptionGroup_traverse(PyBaseExceptionGroupObject *self, + static PyObject * + BaseExceptionGroup_str(PyBaseExceptionGroupObject *self) + { ++ Py_ssize_t num_excs; ++ + assert(self->msg); + assert(PyUnicode_Check(self->msg)); + + assert(PyTuple_CheckExact(self->excs)); +- Py_ssize_t num_excs = PyTuple_Size(self->excs); ++ num_excs = PyTuple_Size(self->excs); + return PyUnicode_FromFormat( + "%S (%zd sub-exception%s)", + self->msg, num_excs, num_excs > 1 ? "s" : ""); +@@ -879,16 +893,19 @@ BaseExceptionGroup_str(PyBaseExceptionGroupObject *self) + static PyObject * + BaseExceptionGroup_derive(PyObject *self_, PyObject *args) + { +- PyBaseExceptionGroupObject *self = _PyBaseExceptionGroupObject_cast(self_); +- PyObject *excs = NULL; ++ PyBaseExceptionGroupObject *self; ++ PyObject *excs, *init_args, *eg; ++ ++ self = _PyBaseExceptionGroupObject_cast(self_); ++ excs = NULL; + if (!PyArg_ParseTuple(args, "O", &excs)) { + return NULL; + } +- PyObject *init_args = PyTuple_Pack(2, self->msg, excs); ++ init_args = PyTuple_Pack(2, self->msg, excs); + if (!init_args) { + return NULL; + } +- PyObject *eg = PyObject_CallObject( ++ eg = PyObject_CallObject( + PyExc_BaseExceptionGroup, init_args); + Py_DECREF(init_args); + return eg; +@@ -898,6 +915,10 @@ static int + exceptiongroup_subset( + PyBaseExceptionGroupObject *_orig, PyObject *excs, PyObject **result) + { ++ PyObject *orig, *eg, *tb, *notes, *notes_copy; ++ Py_ssize_t num_excs; ++ int res; ++ + /* Sets *result to an ExceptionGroup wrapping excs with metadata from + * _orig. If excs is empty, sets *result to NULL. + * Returns 0 on success and -1 on error. +@@ -906,10 +927,10 @@ exceptiongroup_subset( + * so excs is the matching or non-matching sub-sequence of orig->excs + * (this function does not verify that it is a subsequence). + */ +- PyObject *orig = (PyObject *)_orig; ++ orig = (PyObject *)_orig; + + *result = NULL; +- Py_ssize_t num_excs = PySequence_Size(excs); ++ num_excs = PySequence_Size(excs); + if (num_excs < 0) { + return -1; + } +@@ -917,7 +938,7 @@ exceptiongroup_subset( + return 0; + } + +- PyObject *eg = PyObject_CallMethod( ++ eg = PyObject_CallMethod( + orig, "derive", "(O)", excs); + if (!eg) { + return -1; +@@ -931,9 +952,9 @@ exceptiongroup_subset( + + /* Now we hold a reference to the new eg */ + +- PyObject *tb = PyException_GetTraceback(orig); ++ tb = PyException_GetTraceback(orig); + if (tb) { +- int res = PyException_SetTraceback(eg, tb); ++ res = PyException_SetTraceback(eg, tb); + Py_DECREF(tb); + if (res < 0) { + goto error; +@@ -942,19 +963,18 @@ exceptiongroup_subset( + PyException_SetContext(eg, PyException_GetContext(orig)); + PyException_SetCause(eg, PyException_GetCause(orig)); + +- PyObject *notes; + if (_PyObject_LookupAttr(orig, &_Py_ID(__notes__), ¬es) < 0) { + goto error; + } + if (notes) { + if (PySequence_Check(notes)) { + /* Make a copy so the parts have independent notes lists. */ +- PyObject *notes_copy = PySequence_List(notes); ++ notes_copy = PySequence_List(notes); + Py_DECREF(notes); + if (notes_copy == NULL) { + goto error; + } +- int res = PyObject_SetAttr(eg, &_Py_ID(__notes__), notes_copy); ++ res = PyObject_SetAttr(eg, &_Py_ID(__notes__), notes_copy); + Py_DECREF(notes_copy); + if (res < 0) { + goto error; +@@ -992,6 +1012,8 @@ static int + get_matcher_type(PyObject *value, + _exceptiongroup_split_matcher_type *type) + { ++ Py_ssize_t n, i; ++ + assert(value); + + if (PyFunction_Check(value)) { +@@ -1005,8 +1027,8 @@ get_matcher_type(PyObject *value, + } + + if (PyTuple_CheckExact(value)) { +- Py_ssize_t n = PyTuple_GET_SIZE(value); +- for (Py_ssize_t i=0; imatch = NULL; + result->rest = NULL; + +- int is_match = exceptiongroup_split_check_match( ++ is_match = exceptiongroup_split_check_match( + exc, matcher_type, matcher_value); + if (is_match < 0) { + return -1; +@@ -1096,21 +1127,21 @@ exceptiongroup_split_recursive(PyObject *exc, + + /* Partial match */ + +- PyBaseExceptionGroupObject *eg = _PyBaseExceptionGroupObject_cast(exc); ++ eg = _PyBaseExceptionGroupObject_cast(exc); + assert(PyTuple_CheckExact(eg->excs)); +- Py_ssize_t num_excs = PyTuple_Size(eg->excs); ++ num_excs = PyTuple_Size(eg->excs); + if (num_excs < 0) { + return -1; + } + assert(num_excs > 0); /* checked in constructor, and excs is read-only */ + +- int retval = -1; +- PyObject *match_list = PyList_New(0); ++ retval = -1; ++ match_list = PyList_New(0); + if (!match_list) { + return -1; + } + +- PyObject *rest_list = NULL; ++ rest_list = NULL; + if (construct_rest) { + rest_list = PyList_New(0); + if (!rest_list) { +@@ -1118,9 +1149,8 @@ exceptiongroup_split_recursive(PyObject *exc, + } + } + /* recursive calls */ +- for (Py_ssize_t i = 0; i < num_excs; i++) { +- PyObject *e = PyTuple_GET_ITEM(eg->excs, i); +- _exceptiongroup_split_result rec_result; ++ for (i = 0; i < num_excs; i++) { ++ e = PyTuple_GET_ITEM(eg->excs, i); + if (_Py_EnterRecursiveCall(" in exceptiongroup_split_recursive")) { + goto done; + } +@@ -1179,25 +1209,27 @@ exceptiongroup_split_recursive(PyObject *exc, + static PyObject * + BaseExceptionGroup_split(PyObject *self, PyObject *args) + { +- PyObject *matcher_value = NULL; ++ PyObject *matcher_value = NULL, *result; ++ _exceptiongroup_split_matcher_type matcher_type; ++ _exceptiongroup_split_result split_result; ++ bool construct_rest; ++ + if (!PyArg_UnpackTuple(args, "split", 1, 1, &matcher_value)) { + return NULL; + } + +- _exceptiongroup_split_matcher_type matcher_type; + if (get_matcher_type(matcher_value, &matcher_type) < 0) { + return NULL; + } + +- _exceptiongroup_split_result split_result; +- bool construct_rest = true; ++ construct_rest = true; + if (exceptiongroup_split_recursive( + self, matcher_type, matcher_value, + construct_rest, &split_result) < 0) { + return NULL; + } + +- PyObject *result = PyTuple_Pack( ++ result = PyTuple_Pack( + 2, + split_result.match ? split_result.match : Py_None, + split_result.rest ? split_result.rest : Py_None); +@@ -1210,25 +1242,27 @@ BaseExceptionGroup_split(PyObject *self, PyObject *args) + static PyObject * + BaseExceptionGroup_subgroup(PyObject *self, PyObject *args) + { +- PyObject *matcher_value = NULL; ++ PyObject *matcher_value = NULL, *result; ++ _exceptiongroup_split_matcher_type matcher_type; ++ _exceptiongroup_split_result split_result; ++ bool construct_rest; ++ + if (!PyArg_UnpackTuple(args, "subgroup", 1, 1, &matcher_value)) { + return NULL; + } + +- _exceptiongroup_split_matcher_type matcher_type; + if (get_matcher_type(matcher_value, &matcher_type) < 0) { + return NULL; + } + +- _exceptiongroup_split_result split_result; +- bool construct_rest = false; ++ construct_rest = false; + if (exceptiongroup_split_recursive( + self, matcher_type, matcher_value, + construct_rest, &split_result) < 0) { + return NULL; + } + +- PyObject *result = Py_NewRef( ++ result = Py_NewRef( + split_result.match ? split_result.match : Py_None); + + Py_XDECREF(split_result.match); +@@ -1239,6 +1273,11 @@ BaseExceptionGroup_subgroup(PyObject *self, PyObject *args) + static int + collect_exception_group_leaf_ids(PyObject *exc, PyObject *leaf_ids) + { ++ PyObject *exc_id, *e; ++ PyBaseExceptionGroupObject *eg; ++ Py_ssize_t num_excs, i; ++ int res; ++ + if (Py_IsNone(exc)) { + return 0; + } +@@ -1249,23 +1288,22 @@ collect_exception_group_leaf_ids(PyObject *exc, PyObject *leaf_ids) + /* Add IDs of all leaf exceptions in exc to the leaf_ids set */ + + if (!_PyBaseExceptionGroup_Check(exc)) { +- PyObject *exc_id = PyLong_FromVoidPtr(exc); ++ exc_id = PyLong_FromVoidPtr(exc); + if (exc_id == NULL) { + return -1; + } +- int res = PySet_Add(leaf_ids, exc_id); ++ res = PySet_Add(leaf_ids, exc_id); + Py_DECREF(exc_id); + return res; + } +- PyBaseExceptionGroupObject *eg = _PyBaseExceptionGroupObject_cast(exc); +- Py_ssize_t num_excs = PyTuple_GET_SIZE(eg->excs); +- /* recursive calls */ +- for (Py_ssize_t i = 0; i < num_excs; i++) { +- PyObject *e = PyTuple_GET_ITEM(eg->excs, i); ++ eg = _PyBaseExceptionGroupObject_cast(exc); ++ num_excs = PyTuple_GET_SIZE(eg->excs); ++ for (i = 0; i < num_excs; i++) { ++ e = PyTuple_GET_ITEM(eg->excs, i); + if (_Py_EnterRecursiveCall(" in collect_exception_group_leaf_ids")) { + return -1; + } +- int res = collect_exception_group_leaf_ids(e, leaf_ids); ++ res = collect_exception_group_leaf_ids(e, leaf_ids); + _Py_LeaveRecursiveCall(); + if (res < 0) { + return -1; +@@ -1283,17 +1321,23 @@ collect_exception_group_leaf_ids(PyObject *exc, PyObject *leaf_ids) + static PyObject * + exception_group_projection(PyObject *eg, PyObject *keep) + { ++ PyObject *leaf_ids, *e, *result; ++ Py_ssize_t n, i; ++ _exceptiongroup_split_result split_result; ++ bool construct_rest; ++ int err; ++ + assert(_PyBaseExceptionGroup_Check(eg)); + assert(PyList_CheckExact(keep)); + +- PyObject *leaf_ids = PySet_New(NULL); ++ leaf_ids = PySet_New(NULL); + if (!leaf_ids) { + return NULL; + } + +- Py_ssize_t n = PyList_GET_SIZE(keep); +- for (Py_ssize_t i = 0; i < n; i++) { +- PyObject *e = PyList_GET_ITEM(keep, i); ++ n = PyList_GET_SIZE(keep); ++ for (i = 0; i < n; i++) { ++ e = PyList_GET_ITEM(keep, i); + assert(e != NULL); + assert(_PyBaseExceptionGroup_Check(e)); + if (collect_exception_group_leaf_ids(e, leaf_ids) < 0) { +@@ -1302,9 +1346,8 @@ exception_group_projection(PyObject *eg, PyObject *keep) + } + } + +- _exceptiongroup_split_result split_result; +- bool construct_rest = false; +- int err = exceptiongroup_split_recursive( ++ construct_rest = false; ++ err = exceptiongroup_split_recursive( + eg, EXCEPTION_GROUP_MATCH_INSTANCE_IDS, leaf_ids, + construct_rest, &split_result); + Py_DECREF(leaf_ids); +@@ -1312,7 +1355,7 @@ exception_group_projection(PyObject *eg, PyObject *keep) + return NULL; + } + +- PyObject *result = split_result.match ? ++ result = split_result.match ? + split_result.match : Py_NewRef(Py_None); + assert(split_result.rest == NULL); + return result; +@@ -1321,11 +1364,13 @@ exception_group_projection(PyObject *eg, PyObject *keep) + static bool + is_same_exception_metadata(PyObject *exc1, PyObject *exc2) + { ++ PyBaseExceptionObject *e1, *e2; ++ + assert(PyExceptionInstance_Check(exc1)); + assert(PyExceptionInstance_Check(exc2)); + +- PyBaseExceptionObject *e1 = (PyBaseExceptionObject *)exc1; +- PyBaseExceptionObject *e2 = (PyBaseExceptionObject *)exc2; ++ e1 = (PyBaseExceptionObject *)exc1; ++ e2 = (PyBaseExceptionObject *)exc2; + + return (e1->notes == e2->notes && + e1->traceback == e2->traceback && +@@ -1352,10 +1397,16 @@ is_same_exception_metadata(PyObject *exc1, PyObject *exc2) + PyObject * + _PyExc_PrepReraiseStar(PyObject *orig, PyObject *excs) + { ++ Py_ssize_t numexcs, i, num_raised; ++ PyObject *e, *raised_list, *reraised_list, *result, *append_list; ++ PyObject *reraised_eg; ++ bool is_reraise; ++ int res; ++ + assert(PyExceptionInstance_Check(orig)); + assert(PyList_Check(excs)); + +- Py_ssize_t numexcs = PyList_GET_SIZE(excs); ++ numexcs = PyList_GET_SIZE(excs); + + if (numexcs == 0) { + return Py_NewRef(Py_None); +@@ -1368,16 +1419,16 @@ _PyExc_PrepReraiseStar(PyObject *orig, PyObject *excs) + + assert(numexcs == 1 || (numexcs == 2 && PyList_GET_ITEM(excs, 1) == Py_None)); + +- PyObject *e = PyList_GET_ITEM(excs, 0); ++ e = PyList_GET_ITEM(excs, 0); + assert(e != NULL); + return Py_NewRef(e); + } + +- PyObject *raised_list = PyList_New(0); ++ raised_list = PyList_New(0); + if (raised_list == NULL) { + return NULL; + } +- PyObject* reraised_list = PyList_New(0); ++ reraised_list = PyList_New(0); + if (reraised_list == NULL) { + Py_DECREF(raised_list); + return NULL; +@@ -1385,23 +1436,23 @@ _PyExc_PrepReraiseStar(PyObject *orig, PyObject *excs) + + /* Now we are holding refs to raised_list and reraised_list */ + +- PyObject *result = NULL; ++ result = NULL; + + /* Split excs into raised and reraised by comparing metadata with orig */ +- for (Py_ssize_t i = 0; i < numexcs; i++) { +- PyObject *e = PyList_GET_ITEM(excs, i); ++ for (i = 0; i < numexcs; i++) { ++ e = PyList_GET_ITEM(excs, i); + assert(e != NULL); + if (Py_IsNone(e)) { + continue; + } +- bool is_reraise = is_same_exception_metadata(e, orig); +- PyObject *append_list = is_reraise ? reraised_list : raised_list; ++ is_reraise = is_same_exception_metadata(e, orig); ++ append_list = is_reraise ? reraised_list : raised_list; + if (PyList_Append(append_list, e) < 0) { + goto done; + } + } + +- PyObject *reraised_eg = exception_group_projection(orig, reraised_list); ++ reraised_eg = exception_group_projection(orig, reraised_list); + if (reraised_eg == NULL) { + goto done; + } +@@ -1409,12 +1460,12 @@ _PyExc_PrepReraiseStar(PyObject *orig, PyObject *excs) + if (!Py_IsNone(reraised_eg)) { + assert(is_same_exception_metadata(reraised_eg, orig)); + } +- Py_ssize_t num_raised = PyList_GET_SIZE(raised_list); ++ num_raised = PyList_GET_SIZE(raised_list); + if (num_raised == 0) { + result = reraised_eg; + } + else if (num_raised > 0) { +- int res = 0; ++ res = 0; + if (!Py_IsNone(reraised_eg)) { + res = PyList_Append(raised_list, reraised_eg); + } +@@ -1467,9 +1518,12 @@ ComplexExtendsException(PyExc_BaseException, BaseExceptionGroup, + */ + static PyObject* + create_exception_group_class(void) { +- struct _Py_exc_state *state = get_exc_state(); ++ struct _Py_exc_state *state; ++ PyObject *bases; ++ ++ state = get_exc_state(); + +- PyObject *bases = PyTuple_Pack( ++ bases = PyTuple_Pack( + 2, PyExc_BaseExceptionGroup, PyExc_Exception); + if (bases == NULL) { + return NULL; +@@ -1820,6 +1874,7 @@ OSError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + PyOSErrorObject *self = NULL; + PyObject *myerrno = NULL, *strerror = NULL; + PyObject *filename = NULL, *filename2 = NULL; ++ struct _Py_exc_state *state; + #ifdef MS_WINDOWS + PyObject *winerror = NULL; + #endif +@@ -1838,7 +1893,7 @@ OSError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + )) + goto error; + +- struct _Py_exc_state *state = get_exc_state(); ++ state = get_exc_state(); + if (myerrno && PyLong_Check(myerrno) && + state->errnomap && (PyObject *) type == PyExc_OSError) { + PyObject *newtype; +@@ -2062,6 +2117,8 @@ OSError_written_get(PyOSErrorObject *self, void *context) + static int + OSError_written_set(PyOSErrorObject *self, PyObject *arg, void *context) + { ++ Py_ssize_t n; ++ + if (arg == NULL) { + if (self->written == -1) { + PyErr_SetString(PyExc_AttributeError, "characters_written"); +@@ -2070,7 +2127,6 @@ OSError_written_set(PyOSErrorObject *self, PyObject *arg, void *context) + self->written = -1; + return 0; + } +- Py_ssize_t n; + n = PyNumber_AsSsize_t(arg, PyExc_ValueError); + if (n == -1 && PyErr_Occurred()) + return -1; +@@ -2181,12 +2237,13 @@ NameError_init(PyNameErrorObject *self, PyObject *args, PyObject *kwds) + { + static char *kwlist[] = {"name", NULL}; + PyObject *name = NULL; ++ PyObject *empty_tuple; + + if (BaseException_init((PyBaseExceptionObject *)self, args, NULL) == -1) { + return -1; + } + +- PyObject *empty_tuple = PyTuple_New(0); ++ empty_tuple = PyTuple_New(0); + if (!empty_tuple) { + return -1; + } +@@ -2256,12 +2313,13 @@ AttributeError_init(PyAttributeErrorObject *self, PyObject *args, PyObject *kwds + static char *kwlist[] = {"name", "obj", NULL}; + PyObject *name = NULL; + PyObject *obj = NULL; ++ PyObject *empty_tuple; + + if (BaseException_init((PyBaseExceptionObject *)self, args, NULL) == -1) { + return -1; + } + +- PyObject *empty_tuple = PyTuple_New(0); ++ empty_tuple = PyTuple_New(0); + if (!empty_tuple) { + return -1; + } +@@ -3238,6 +3296,7 @@ static PyObject * + MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + { + PyBaseExceptionObject *self; ++ struct _Py_exc_state *state; + + /* If this is a subclass of MemoryError, don't use the freelist + * and just return a fresh object */ +@@ -3245,7 +3304,7 @@ MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + return BaseException_new(type, args, kwds); + } + +- struct _Py_exc_state *state = get_exc_state(); ++ state = get_exc_state(); + if (state->memerrors_freelist == NULL) { + return BaseException_new(type, args, kwds); + } +@@ -3270,6 +3329,8 @@ MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + static void + MemoryError_dealloc(PyBaseExceptionObject *self) + { ++ struct _Py_exc_state *state; ++ + _PyObject_GC_UNTRACK(self); + + BaseException_clear(self); +@@ -3281,7 +3342,7 @@ MemoryError_dealloc(PyBaseExceptionObject *self) + return; + } + +- struct _Py_exc_state *state = get_exc_state(); ++ state = get_exc_state(); + if (state->memerrors_numfree >= MEMERRORS_SAVE) { + Py_TYPE(self)->tp_free((PyObject *)self); + } +@@ -3591,12 +3652,15 @@ static struct static_exception static_exceptions[] = { + int + _PyExc_InitTypes(PyInterpreterState *interp) + { ++ size_t i; ++ PyTypeObject *exc; ++ + if (!_Py_IsMainInterpreter(interp)) { + return 0; + } + +- for (size_t i=0; i < Py_ARRAY_LENGTH(static_exceptions); i++) { +- PyTypeObject *exc = static_exceptions[i].exc; ++ for (i = 0; i < Py_ARRAY_LENGTH(static_exceptions); i++) { ++ exc = static_exceptions[i].exc; + + if (PyType_Ready(exc) < 0) { + return -1; +@@ -3609,12 +3673,15 @@ _PyExc_InitTypes(PyInterpreterState *interp) + static void + _PyExc_FiniTypes(PyInterpreterState *interp) + { ++ Py_ssize_t i; ++ PyTypeObject *exc; ++ + if (!_Py_IsMainInterpreter(interp)) { + return; + } + +- for (Py_ssize_t i=Py_ARRAY_LENGTH(static_exceptions) - 1; i >= 0; i--) { +- PyTypeObject *exc = static_exceptions[i].exc; ++ for (i = Py_ARRAY_LENGTH(static_exceptions) - 1; i >= 0; i--) { ++ exc = static_exceptions[i].exc; + _PyStaticType_Dealloc(exc); + } + } +@@ -3693,20 +3760,24 @@ _PyExc_InitState(PyInterpreterState *interp) + int + _PyBuiltins_AddExceptions(PyObject *bltinmod) + { +- PyObject *mod_dict = PyModule_GetDict(bltinmod); ++ PyObject *mod_dict, *PyExc_ExceptionGroup; ++ struct static_exception item; ++ size_t i; ++ ++ mod_dict = PyModule_GetDict(bltinmod); + if (mod_dict == NULL) { + return -1; + } + +- for (size_t i=0; i < Py_ARRAY_LENGTH(static_exceptions); i++) { +- struct static_exception item = static_exceptions[i]; ++ for (i = 0; i < Py_ARRAY_LENGTH(static_exceptions); i++) { ++ item = static_exceptions[i]; + + if (PyDict_SetItemString(mod_dict, item.name, (PyObject*)item.exc)) { + return -1; + } + } + +- PyObject *PyExc_ExceptionGroup = create_exception_group_class(); ++ PyExc_ExceptionGroup = create_exception_group_class(); + if (!PyExc_ExceptionGroup) { + return -1; + } +diff --git a/Objects/fileobject.c b/Objects/fileobject.c +index ffe55eb..7287abd 100644 +--- a/Objects/fileobject.c ++++ b/Objects/fileobject.c +@@ -499,6 +499,7 @@ PyFile_SetOpenCodeHook(Py_OpenCodeHookFunction hook, void *userData) { + PyObject * + PyFile_OpenCodeObject(PyObject *path) + { ++ Py_OpenCodeHookFunction hook; + PyObject *iomod, *f = NULL; + + if (!PyUnicode_Check(path)) { +@@ -507,7 +508,7 @@ PyFile_OpenCodeObject(PyObject *path) + return NULL; + } + +- Py_OpenCodeHookFunction hook = _PyRuntime.open_code_hook; ++ hook = _PyRuntime.open_code_hook; + if (hook) { + f = hook(path, _PyRuntime.open_code_userdata); + } else { +diff --git a/Objects/floatobject.c b/Objects/floatobject.c +index 29a74f2..4a7c392 100644 +--- a/Objects/floatobject.c ++++ b/Objects/floatobject.c +@@ -254,10 +254,15 @@ PyFloat_FromString(PyObject *v) + void + _PyFloat_ExactDealloc(PyObject *obj) + { ++ PyFloatObject *op; ++#if PyFloat_MAXFREELIST > 0 ++ struct _Py_float_state *state; ++#endif ++ + assert(PyFloat_CheckExact(obj)); +- PyFloatObject *op = (PyFloatObject *)obj; ++ op = (PyFloatObject *)obj; + #if PyFloat_MAXFREELIST > 0 +- struct _Py_float_state *state = get_float_state(); ++ state = get_float_state(); + #ifdef Py_DEBUG + // float_dealloc() must not be called after _PyFloat_Fini() + assert(state->numfree != -1); +@@ -309,11 +314,11 @@ PyFloat_AsDouble(PyObject *op) + nb = Py_TYPE(op)->tp_as_number; + if (nb == NULL || nb->nb_float == NULL) { + if (nb && nb->nb_index) { +- PyObject *res = _PyNumber_Index(op); ++ res = _PyNumber_Index(op); + if (!res) { + return -1; + } +- double val = PyLong_AsDouble(res); ++ val = PyLong_AsDouble(res); + Py_DECREF(res); + return val; + } +@@ -1703,16 +1708,19 @@ static PyObject * + float_vectorcall(PyObject *type, PyObject * const*args, + size_t nargsf, PyObject *kwnames) + { ++ Py_ssize_t nargs; ++ PyObject *x; ++ + if (!_PyArg_NoKwnames("float", kwnames)) { + return NULL; + } + +- Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); ++ nargs = PyVectorcall_NARGS(nargsf); + if (!_PyArg_CheckPositional("float", nargs, 0, 1)) { + return NULL; + } + +- PyObject *x = nargs >= 1 ? args[0] : NULL; ++ x = nargs >= 1 ? args[0] : NULL; + return float_new_impl(_PyType_CAST(type), x); + } + +@@ -1932,18 +1940,28 @@ PyTypeObject PyFloat_Type = { + 0, /* tp_init */ + 0, /* tp_alloc */ + float_new, /* tp_new */ +- .tp_vectorcall = (vectorcallfunc)float_vectorcall, ++ 0, /* tp_free */ ++ 0, /* tp_is_gc */ ++ 0, /* tp_bases */ ++ 0, /* tp_mro */ ++ 0, /* tp_cache */ ++ 0, /* tp_subclasses */ ++ 0, /* tp_weaklist */ ++ 0, /* tp_del */ ++ 0, /* tp_version_tag */ ++ 0, /* tp_finalize */ ++ (vectorcallfunc)float_vectorcall, /* tp_vectorcall */ + }; + + void + _PyFloat_InitState(PyInterpreterState *interp) + { ++ float_format_type detected_double_format, detected_float_format; ++ + if (!_Py_IsMainInterpreter(interp)) { + return; + } + +- float_format_type detected_double_format, detected_float_format; +- + /* We attempt to determine if this machine is using IEEE + floating point formats by peering at the bits of some + carefully chosen values. If it looks like we are on an +@@ -2256,13 +2274,13 @@ PyFloat_Pack4(double x, char *data, int le) + + } + else { ++ unsigned char s[sizeof(float)]; + float y = (float)x; + int i, incr = 1; + + if (Py_IS_INFINITY(y) && !Py_IS_INFINITY(x)) + goto Overflow; + +- unsigned char s[sizeof(float)]; + memcpy(s, &y, sizeof(float)); + + if ((float_format == ieee_little_endian_format && !le) +diff --git a/Objects/frameobject.c b/Objects/frameobject.c +index c95e871..5c2f86f 100644 +--- a/Objects/frameobject.c ++++ b/Objects/frameobject.c +@@ -25,9 +25,11 @@ static PyMemberDef frame_memberlist[] = { + static PyObject * + frame_getlocals(PyFrameObject *f, void *closure) + { ++ PyObject *locals; ++ + if (PyFrame_FastToLocalsWithError(f) < 0) + return NULL; +- PyObject *locals = f->f_frame->f_locals; ++ locals = f->f_frame->f_locals; + Py_INCREF(locals); + return locals; + } +@@ -161,7 +163,7 @@ compatible_kind(Kind from, Kind to) { + #define OVERFLOWED -1 + + #define MAX_STACK_ENTRIES (63/BITS_PER_BLOCK) +-#define WILL_OVERFLOW (1ULL<<((MAX_STACK_ENTRIES-1)*BITS_PER_BLOCK)) ++#define WILL_OVERFLOW (PY_ULL(1)<<((MAX_STACK_ENTRIES-1)*BITS_PER_BLOCK)) + + #define EMPTY_STACK 0 + +@@ -200,22 +202,28 @@ peek(int64_t stack, int n) + static Kind + stack_swap(int64_t stack, int n) + { ++ Kind to_swap, top; ++ int shift; ++ int64_t replaced_low, replaced_top; ++ + assert(n >= 1); +- Kind to_swap = peek(stack, n); +- Kind top = top_of_stack(stack); +- int shift = BITS_PER_BLOCK*(n-1); +- int64_t replaced_low = (stack & ~(MASK << shift)) | (top << shift); +- int64_t replaced_top = (replaced_low & ~MASK) | to_swap; ++ to_swap = peek(stack, n); ++ top = top_of_stack(stack); ++ shift = BITS_PER_BLOCK*(n-1); ++ replaced_low = (stack & ~(MASK << shift)) | (top << shift); ++ replaced_top = (replaced_low & ~MASK) | to_swap; + return replaced_top; + } + + static int64_t + pop_to_level(int64_t stack, int level) { ++ int64_t max_item, level_max_stack; ++ + if (level == 0) { + return EMPTY_STACK; + } +- int64_t max_item = (1< level_max_stack) { + stack = pop_value(stack); + } +@@ -276,20 +284,29 @@ print_stacks(int64_t *stacks, int n) { + static int64_t * + mark_stacks(PyCodeObject *code_obj, int len) + { +- PyObject *co_code = _PyCode_GetCode(code_obj); ++ PyObject *co_code; ++ _Py_CODEUNIT *code; ++ int64_t *stacks; ++ int i, j, opcode, todo; ++ int64_t next_stack, target_stack; ++ int n, delta; ++ unsigned char *start, *end, *scan; ++ int start_offset, size, handler, depth_and_lasti, level, lasti; ++ uint64_t exception_target_stack; ++ ++ co_code = _PyCode_GetCode(code_obj); + if (co_code == NULL) { + return NULL; + } +- _Py_CODEUNIT *code = (_Py_CODEUNIT *)PyBytes_AS_STRING(co_code); +- int64_t *stacks = PyMem_New(int64_t, len+1); +- int i, j, opcode; ++ code = (_Py_CODEUNIT *)PyBytes_AS_STRING(co_code); ++ stacks = PyMem_New(int64_t, len+1); + + if (stacks == NULL) { + PyErr_NoMemory(); + Py_DECREF(co_code); + return NULL; + } +- for (int i = 1; i <= len; i++) { ++ for (i = 1; i <= len; i++) { + stacks[i] = UNINITIALIZED; + } + stacks[0] = EMPTY_STACK; +@@ -298,12 +315,12 @@ mark_stacks(PyCodeObject *code_obj, int len) + // Generators get sent None while starting: + stacks[0] = push_value(stacks[0], Object); + } +- int todo = 1; ++ todo = 1; + while (todo) { + todo = 0; + /* Scan instructions */ + for (i = 0; i < len; i++) { +- int64_t next_stack = stacks[i]; ++ next_stack = stacks[i]; + if (next_stack == UNINITIALIZED) { + continue; + } +@@ -320,8 +337,7 @@ mark_stacks(PyCodeObject *code_obj, int len) + case POP_JUMP_FORWARD_IF_NOT_NONE: + case POP_JUMP_BACKWARD_IF_NOT_NONE: + { +- int64_t target_stack; +- int j = get_arg(code, i); ++ j = get_arg(code, i); + if (opcode == POP_JUMP_FORWARD_IF_FALSE || + opcode == POP_JUMP_FORWARD_IF_TRUE || + opcode == JUMP_IF_FALSE_OR_POP || +@@ -388,7 +404,7 @@ mark_stacks(PyCodeObject *code_obj, int len) + break; + case FOR_ITER: + { +- int64_t target_stack = pop_value(next_stack); ++ target_stack = pop_value(next_stack); + stacks[i+1] = push_value(next_stack, Object); + j = get_arg(code, i) + i + 1; + assert(j < len); +@@ -446,21 +462,21 @@ mark_stacks(PyCodeObject *code_obj, int len) + } + case SWAP: + { +- int n = get_arg(code, i); ++ n = get_arg(code, i); + next_stack = stack_swap(next_stack, n); + stacks[i+1] = next_stack; + break; + } + case COPY: + { +- int n = get_arg(code, i); ++ n = get_arg(code, i); + next_stack = push_value(next_stack, peek(next_stack, n)); + stacks[i+1] = next_stack; + break; + } + default: + { +- int delta = PyCompile_OpcodeStackEffect(opcode, get_arg(code, i)); ++ delta = PyCompile_OpcodeStackEffect(opcode, get_arg(code, i)); + assert(delta != PY_INVALID_STACK_EFFECT); + while (delta < 0) { + next_stack = pop_value(next_stack); +@@ -475,30 +491,28 @@ mark_stacks(PyCodeObject *code_obj, int len) + } + } + /* Scan exception table */ +- unsigned char *start = (unsigned char *)PyBytes_AS_STRING(code_obj->co_exceptiontable); +- unsigned char *end = start + PyBytes_GET_SIZE(code_obj->co_exceptiontable); +- unsigned char *scan = start; ++ start = (unsigned char *)PyBytes_AS_STRING(code_obj->co_exceptiontable); ++ end = start + PyBytes_GET_SIZE(code_obj->co_exceptiontable); ++ scan = start; + while (scan < end) { +- int start_offset, size, handler; + scan = parse_varint(scan, &start_offset); + assert(start_offset >= 0 && start_offset < len); + scan = parse_varint(scan, &size); + assert(size >= 0 && start_offset+size <= len); + scan = parse_varint(scan, &handler); + assert(handler >= 0 && handler < len); +- int depth_and_lasti; + scan = parse_varint(scan, &depth_and_lasti); +- int level = depth_and_lasti >> 1; +- int lasti = depth_and_lasti & 1; ++ level = depth_and_lasti >> 1; ++ lasti = depth_and_lasti & 1; + if (stacks[start_offset] != UNINITIALIZED) { + if (stacks[handler] == UNINITIALIZED) { + todo = 1; +- uint64_t target_stack = pop_to_level(stacks[start_offset], level); ++ exception_target_stack = pop_to_level(stacks[start_offset], level); + if (lasti) { +- target_stack = push_value(target_stack, Lasti); ++ exception_target_stack = push_value(exception_target_stack, Lasti); + } +- target_stack = push_value(target_stack, Except); +- stacks[handler] = target_stack; ++ exception_target_stack = push_value(exception_target_stack, Except); ++ stacks[handler] = exception_target_stack; + } + } + } +@@ -531,6 +545,8 @@ compatible_stack(int64_t from_stack, int64_t to_stack) + static const char * + explain_incompatible_stack(int64_t to_stack) + { ++ Kind target_kind; ++ + assert(to_stack != 0); + if (to_stack == OVERFLOWED) { + return "stack is too deep to analyze"; +@@ -538,7 +554,7 @@ explain_incompatible_stack(int64_t to_stack) + if (to_stack == UNINITIALIZED) { + return "can't jump into an exception handler, or code may be unreachable"; + } +- Kind target_kind = top_of_stack(to_stack); ++ target_kind = top_of_stack(to_stack); + switch(target_kind) { + case Except: + return "can't jump into an 'except' block as there's no exception"; +@@ -558,15 +574,19 @@ static int * + marklines(PyCodeObject *code, int len) + { + PyCodeAddressRange bounds; ++ int last_line; ++ int *linestarts; ++ int i; ++ + _PyCode_InitAddressRange(code, &bounds); + assert (bounds.ar_end == 0); +- int last_line = -1; ++ last_line = -1; + +- int *linestarts = PyMem_New(int, len); ++ linestarts = PyMem_New(int, len); + if (linestarts == NULL) { + return NULL; + } +- for (int i = 0; i < len; i++) { ++ for (i = 0; i < len; i++) { + linestarts[i] = -1; + } + +@@ -583,8 +603,10 @@ marklines(PyCodeObject *code, int len) + static int + first_line_not_before(int *lines, int len, int line) + { +- int result = INT_MAX; +- for (int i = 0; i < len; i++) { ++ int result, i; ++ ++ result = INT_MAX; ++ for (i = 0; i < len; i++) { + if (lines[i] < result && lines[i] >= line) { + result = lines[i]; + } +@@ -648,6 +670,8 @@ _PyFrame_GetState(PyFrameObject *frame) + static int + frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignored)) + { ++ int i; ++ + if (p_new_lineno == NULL) { + PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); + return -1; +@@ -748,7 +772,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore + int64_t start_stack = stacks[_PyInterpreterFrame_LASTI(f->f_frame)]; + int err = -1; + const char *msg = "cannot find bytecode for specified line"; +- for (int i = 0; i < len; i++) { ++ for (i = 0; i < len; i++) { + if (lines[i] == new_lineno) { + int64_t target_stack = stacks[i]; + if (compatible_stack(start_stack, target_stack)) { diff --git a/Objects/object.c b/Objects/object.c -index c4f2786..054bbed 100644 +index c4f2786..72ba7d5 100644 --- a/Objects/object.c +++ b/Objects/object.c -@@ -30,6 +30,10 @@ extern "C" { +@@ -30,6 +30,13 @@ extern "C" { /* Defined in tracemalloc.c */ extern void _PyMem_DumpTraceback(int fd, const void *ptr); +#if defined(MS_WINDOWS) && defined(_MSC_VER) && _MSC_VER < 1300 +extern void _PyClassObject_InitTypes(void); ++extern void _PyDesc_InitTypes(void); ++extern void _PyDict_InitTypes(void); ++extern void _PyEnum_InitTypes(void); +#endif + int _PyObject_CheckConsistency(PyObject *op, int check_content) -@@ -1980,6 +1984,10 @@ _PyTypes_InitTypes(PyInterpreterState *interp) +@@ -1980,6 +1987,13 @@ _PyTypes_InitTypes(PyInterpreterState *interp) return _PyStatus_OK(); } +#if defined(MS_WINDOWS) && defined(_MSC_VER) && _MSC_VER < 1300 + _PyClassObject_InitTypes(); ++ _PyDesc_InitTypes(); ++ _PyDict_InitTypes(); ++ _PyEnum_InitTypes(); +#endif + // All other static types (unless initialized elsewhere) for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) { PyTypeObject *type = static_types[i]; +diff --git a/Objects/stringlib/eq.h b/Objects/stringlib/eq.h +index 9c1058b..11ea17d 100644 +--- a/Objects/stringlib/eq.h ++++ b/Objects/stringlib/eq.h +@@ -6,13 +6,16 @@ + Py_LOCAL_INLINE(int) + unicode_eq(PyObject *aa, PyObject *bb) + { ++ PyUnicodeObject *a; ++ PyUnicodeObject *b; ++ + assert(PyUnicode_Check(aa)); + assert(PyUnicode_Check(bb)); + assert(PyUnicode_IS_READY(aa)); + assert(PyUnicode_IS_READY(bb)); + +- PyUnicodeObject *a = (PyUnicodeObject *)aa; +- PyUnicodeObject *b = (PyUnicodeObject *)bb; ++ a = (PyUnicodeObject *)aa; ++ b = (PyUnicodeObject *)bb; + + if (PyUnicode_GET_LENGTH(a) != PyUnicode_GET_LENGTH(b)) + return 0; diff --git a/Objects/stringlib/fastsearch.h b/Objects/stringlib/fastsearch.h index 7403d8a..9912f15 100644 --- a/Objects/stringlib/fastsearch.h diff --git a/scripts/vc6-fileobject-opencode-c89.test.py b/scripts/vc6-fileobject-opencode-c89.test.py new file mode 100644 index 0000000..9a08545 --- /dev/null +++ b/scripts/vc6-fileobject-opencode-c89.test.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +"""Guard VC6 C89 declaration order in PyFile_OpenCodeObject.""" +import sys +from pathlib import Path +from typing import NoReturn + + +def fail(message: str) -> NoReturn: + print(message, file=sys.stderr) + raise SystemExit(1) + + +def function_body(source, signature): + start = source.find(signature) + if start < 0: + fail(f"missing function signature: {signature}") + brace = source.find("{", start + len(signature)) + if brace < 0: + fail("missing function body") + depth = 0 + for end in range(brace, len(source)): + if source[end] == "{": + depth += 1 + elif source[end] == "}": + depth -= 1 + if depth == 0: + return source[brace + 1:end] + fail("unterminated function body") + + +path = Path(sys.argv[1]) +source = path.read_text(encoding="utf-8") +body = function_body(source, "PyFile_OpenCodeObject(PyObject *path)") +expected_decl = " Py_OpenCodeHookFunction hook;" +if expected_decl not in body: + fail("hook must be declared without initializer at function entry") +if "Py_OpenCodeHookFunction hook =" in body: + fail("hook declaration must not be initialized at declaration") +validation = body.find("if (!PyUnicode_Check(path))") +assignment = body.find("hook = _PyRuntime.open_code_hook;") +if validation < 0 or assignment < 0 or assignment < validation: + fail("hook lookup must remain after path validation") +if body.find("return NULL;", validation) > assignment: + fail("hook lookup must remain after invalid-path early return") +print("fileobject open-code hook C89 declaration and validation order: PASS") diff --git a/scripts/vc6-floatobject-pack4-c89.test.py b/scripts/vc6-floatobject-pack4-c89.test.py new file mode 100644 index 0000000..1695972 --- /dev/null +++ b/scripts/vc6-floatobject-pack4-c89.test.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 +"""Guard C89 local ordering in the float32 packing fallback.""" +import sys +from pathlib import Path +from typing import NoReturn + + +def fail(message: str) -> NoReturn: + print(message, file=sys.stderr) + raise SystemExit(1) + + +def extract_function(source: str, signature: str) -> str: + start = source.find(signature) + if start < 0: + fail(f"missing function signature: {signature}") + brace = source.find("{", start + len(signature)) + if brace < 0: + fail("missing function body") + depth = 0 + for end in range(brace, len(source)): + if source[end] == "{": + depth += 1 + elif source[end] == "}": + depth -= 1 + if depth == 0: + return source[brace + 1:end] + fail("unterminated function body") + + +source = Path(sys.argv[1]).read_text(encoding="utf-8") +body = extract_function(source, "PyFloat_Pack4(double x, char *data, int le)") +expected = """ else { + unsigned char s[sizeof(float)]; + float y = (float)x; + int i, incr = 1;""" +if expected not in body: + fail("float32 fallback locals must be declared at the start of its block") +copy = body.find("memcpy(s, &y, sizeof(float));") +infinity_check = body.find("if (Py_IS_INFINITY(y) && !Py_IS_INFINITY(x))") +pack_loop = body.find("for (i = 0; i < 4; i++)") +if min(copy, infinity_check, pack_loop) < 0 or not infinity_check < copy < pack_loop: + fail("float32 fallback must preserve overflow-check/copy/packing order") + +dealloc = extract_function(source, "_PyFloat_ExactDealloc(PyObject *obj)") +if " PyFloatObject *op;" not in dealloc or " PyFloatObject *op =" in dealloc: + fail("float exact deallocator op must be declared without initializer at entry") +if " struct _Py_float_state *state;" not in dealloc or " struct _Py_float_state *state =" in dealloc: + fail("float exact deallocator state must be declared without initializer at entry") +if not dealloc.find("assert(PyFloat_CheckExact(obj));") < dealloc.find("op = (PyFloatObject *)obj;") < dealloc.find("state = get_float_state();"): + fail("float exact deallocator must preserve assert/op/state initialization order") + +as_double = extract_function(source, "PyFloat_AsDouble(PyObject *op)") +if " PyObject *res;" not in as_double or " double val;" not in as_double: + fail("PyFloat_AsDouble temporaries must be declared at function entry") +if "PyObject *res = _PyNumber_Index(op);" in as_double or "double val = PyLong_AsDouble(res);" in as_double: + fail("PyFloat_AsDouble must not redeclare its entry temporaries") +if not as_double.find("res = _PyNumber_Index(op);") < as_double.find("val = PyLong_AsDouble(res);") < as_double.find("Py_DECREF(res);"): + fail("PyFloat_AsDouble must preserve index-convert/decref order") + +vectorcall = extract_function(source, "float_vectorcall(PyObject *type, PyObject * const*args,") +for declaration in (" Py_ssize_t nargs;", " PyObject *x;"): + if declaration not in vectorcall: + fail("float_vectorcall locals must be declared at function entry") +if "Py_ssize_t nargs =" in vectorcall or "PyObject *x =" in vectorcall: + fail("float_vectorcall locals must not be initialized at declaration") +if not vectorcall.find("nargs = PyVectorcall_NARGS(nargsf);") < vectorcall.find("x = nargs >= 1 ? args[0] : NULL;"): + fail("float_vectorcall must preserve nargs-before-argument selection order") + +type_init = extract_function(source, "PyTypeObject PyFloat_Type =") +expected_slots = """ float_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ + 0, /* tp_del */ + 0, /* tp_version_tag */ + 0, /* tp_finalize */ + (vectorcallfunc)float_vectorcall, /* tp_vectorcall */""" +if expected_slots not in type_init or ".tp_vectorcall =" in type_init: + fail("PyFloat_Type vectorcall must use C89 positional trailing slots") + +state_init = extract_function(source, "_PyFloat_InitState(PyInterpreterState *interp)") +format_declaration = " float_format_type detected_double_format, detected_float_format;" +if format_declaration not in state_init: + fail("float format detection locals must be declared at function entry") +if format_declaration in state_init[state_init.find("if (!_Py_IsMainInterpreter(interp))"):]: + fail("float format detection locals must not be declared after a statement") + +clinic = Path(sys.argv[2]).read_text(encoding="utf-8") +wrapper = extract_function(clinic, "float___getformat__(PyTypeObject *type, PyObject *arg)") +declaration = " Py_ssize_t typestr_length;" +if declaration not in wrapper: + fail("float.__getformat__ typestr_length must be declared at wrapper entry") +validation = wrapper.find("if (!PyUnicode_Check(arg))") +assignment = wrapper.find("typestr = PyUnicode_AsUTF8AndSize(arg, &typestr_length);") +if validation < 0 or assignment < validation or "Py_ssize_t typestr_length;" in wrapper[validation:]: + fail("Clinic wrapper must preserve type validation before string conversion") +print("floatobject C89 declarations and generated Clinic validation order: PASS") diff --git a/scripts/vc6-frameobject-c89.test.py b/scripts/vc6-frameobject-c89.test.py new file mode 100644 index 0000000..d79d74f --- /dev/null +++ b/scripts/vc6-frameobject-c89.test.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +"""Guard C89 local ordering in frame_getlocals.""" +import sys +from pathlib import Path +from typing import NoReturn + + +def fail(message: str) -> NoReturn: + print(message, file=sys.stderr) + raise SystemExit(1) + + +def extract_function(source: str, signature: str) -> str: + start = source.find(signature) + if start < 0: + fail(f"missing function signature: {signature}") + brace = source.find("{", start + len(signature)) + if brace < 0: + fail("missing function body") + depth = 0 + for end in range(brace, len(source)): + if source[end] == "{": + depth += 1 + elif source[end] == "}": + depth -= 1 + if depth == 0: + return source[brace + 1:end] + fail("unterminated function body") + + +source = Path(sys.argv[1]).read_text(encoding="utf-8") +if "#define WILL_OVERFLOW (PY_ULL(1)<<((MAX_STACK_ENTRIES-1)*BITS_PER_BLOCK))" not in source: + fail("frame stack overflow threshold must use Python's portable unsigned-long-long macro") +if "#define WILL_OVERFLOW (1ULL<<" in source: + fail("frame stack overflow threshold must not use a compiler-specific ULL literal") +body = extract_function(source, "frame_getlocals(PyFrameObject *f, void *closure)") +declaration = " PyObject *locals;" +if declaration not in body or "PyObject *locals =" in body: + fail("frame_getlocals locals must be declared without initializer at entry") +if not body.find("if (PyFrame_FastToLocalsWithError(f) < 0)") < body.find("locals = f->f_frame->f_locals;") < body.find("Py_INCREF(locals);") < body.find("return locals;"): + fail("frame_getlocals must preserve conversion, lookup, incref, and return order") + +swap = extract_function(source, "stack_swap(int64_t stack, int n)") +for declaration in (" Kind to_swap, top;", " int shift;", " int64_t replaced_low, replaced_top;"): + if declaration not in swap: + fail("stack_swap locals must be declared before its assertion") +if "Kind to_swap =" in swap or "Kind top =" in swap or "int shift =" in swap or "int64_t replaced_low =" in swap or "int64_t replaced_top =" in swap: + fail("stack_swap temporaries must not be initialized after statements") +if not swap.find("assert(n >= 1);") < swap.find("to_swap = peek(stack, n);") < swap.find("top = top_of_stack(stack);") < swap.find("shift = BITS_PER_BLOCK*(n-1);") < swap.find("replaced_low =") < swap.find("replaced_top ="): + fail("stack_swap must preserve peek, top, shift, and replacement order") + +pop_level = extract_function(source, "pop_to_level(int64_t stack, int level)") +if " int64_t max_item, level_max_stack;" not in pop_level: + fail("pop_to_level locals must be declared at function entry") +if "int64_t max_item =" in pop_level or "int64_t level_max_stack =" in pop_level: + fail("pop_to_level locals must not be initialized after the early return") +if not pop_level.find("if (level == 0)") < pop_level.find("max_item = (1< level_max_stack)"): + fail("pop_to_level must preserve level guard and stack reduction order") + +mark = extract_function(source, "mark_stacks(PyCodeObject *code_obj, int len)") +for declaration in ( + " PyObject *co_code;", " _Py_CODEUNIT *code;", " int64_t *stacks;", + " int i, j, opcode, todo;", " int64_t next_stack, target_stack;", + " int n, delta;", " unsigned char *start, *end, *scan;", + " int start_offset, size, handler, depth_and_lasti, level, lasti;", + " uint64_t exception_target_stack;", +): + if declaration not in mark: + fail("mark_stacks locals must be declared at function entry") +if "for (int " in mark or "int64_t target_stack =" in mark or "uint64_t target_stack =" in mark or "int64_t next_stack =" in mark: + fail("mark_stacks must not introduce declarations after statements") +if not mark.find("co_code = _PyCode_GetCode(code_obj);") < mark.find("code = (_Py_CODEUNIT *)PyBytes_AS_STRING(co_code);") < mark.find("stacks = PyMem_New(int64_t, len+1);"): + fail("mark_stacks must preserve code lookup and stack allocation order") + +explain = extract_function(source, "explain_incompatible_stack(int64_t to_stack)") +if " Kind target_kind;" not in explain or "Kind target_kind =" in explain: + fail("explain_incompatible_stack target kind must be declared at function entry") +if not explain.find("assert(to_stack != 0);") < explain.find("target_kind = top_of_stack(to_stack);") < explain.find("switch(target_kind)"): + fail("explain_incompatible_stack must preserve assertion and dispatch order") + +marklines = extract_function(source, "marklines(PyCodeObject *code, int len)") +for declaration in (" PyCodeAddressRange bounds;", " int last_line;", " int *linestarts;", " int i;"): + if declaration not in marklines: + fail("marklines locals must be declared at function entry") +if "int last_line =" in marklines or "int *linestarts =" in marklines or "for (int i =" in marklines: + fail("marklines must not declare locals after statements") +if not marklines.find("_PyCode_InitAddressRange(code, &bounds);") < marklines.find("last_line = -1;") < marklines.find("linestarts = PyMem_New(int, len);") < marklines.find("for (i = 0; i < len; i++)"): + fail("marklines must preserve range-init/allocation/initialization order") + +firstline = extract_function(source, "first_line_not_before(int *lines, int len, int line)") +if " int result, i;" not in firstline or "for (int i =" in firstline: + fail("first_line_not_before loop index must be declared at function entry") +if not firstline.find("result = INT_MAX;") < firstline.find("for (i = 0; i < len; i++)"): + fail("first_line_not_before must initialize its minimum before scanning") +print("frameobject C89 declarations and frame locals ownership order: PASS") diff --git a/scripts/vc6-probe-pythoncore-frontier.test.sh b/scripts/vc6-probe-pythoncore-frontier.test.sh index 02ce45a..0765ee9 100755 --- a/scripts/vc6-probe-pythoncore-frontier.test.sh +++ b/scripts/vc6-probe-pythoncore-frontier.test.sh @@ -9927,6 +9927,24 @@ else bad "bytearray_join C89 declaration preserves export/join/unexport order" fi +if python3 "$REPO_ROOT/scripts/vc6-fileobject-opencode-c89.test.py" "$REPO_ROOT/cpython/Objects/fileobject.c"; then + pass "fileobject open-code hook C89 declaration and validation order" +else + bad "fileobject open-code hook C89 declaration and validation order" +fi + +if python3 "$REPO_ROOT/scripts/vc6-floatobject-pack4-c89.test.py" "$REPO_ROOT/cpython/Objects/floatobject.c" "$REPO_ROOT/cpython/Objects/clinic/floatobject.c.h"; then + pass "floatobject float32 fallback C89 declarations and order" +else + bad "floatobject float32 fallback C89 declarations and order" +fi + +if python3 "$REPO_ROOT/scripts/vc6-frameobject-c89.test.py" "$REPO_ROOT/cpython/Objects/frameobject.c"; then + pass "frameobject frame_getlocals C89 declaration and ownership order" +else + bad "frameobject frame_getlocals C89 declaration and ownership order" +fi + if [ "$fail" -ne 0 ]; then echo "FAILED" exit 1