From 3a7f8dfb96028b4739df1c45590de71cb9c8c77e Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Sat, 16 Apr 2022 21:11:18 -0400 Subject: [PATCH 01/24] initial attempt --- Include/internal/pycore_code.h | 7 ++ Include/internal/pycore_list.h | 6 ++ Include/internal/pycore_range.h | 22 ++++ Include/opcode.h | 167 +++++++++++++++-------------- Lib/opcode.py | 7 +- Makefile.pre.in | 1 + Objects/listobject.c | 40 +++---- Objects/rangeobject.c | 23 ++-- PCbuild/pythoncore.vcxproj | 1 + PCbuild/pythoncore.vcxproj.filters | 3 + Python/ceval.c | 67 ++++++++++-- Python/opcode_targets.h | 62 +++++------ Python/specialize.c | 29 +++++ 13 files changed, 277 insertions(+), 158 deletions(-) create mode 100644 Include/internal/pycore_range.h diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 8c868bcd5b5cbe..ec67da84c2fd5c 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -92,6 +92,12 @@ typedef struct { #define INLINE_CACHE_ENTRIES_STORE_SUBSCR CACHE_ENTRIES(_PyStoreSubscrCache) +typedef struct { + _Py_CODEUNIT counter; +} _PyForIterCache; + +#define INLINE_CACHE_ENTRIES_FOR_ITER CACHE_ENTRIES(_PyForIterCache) + #define QUICKENING_WARMUP_DELAY 8 /* We want to compare to zero for efficiency, so we offset values accordingly */ @@ -270,6 +276,7 @@ extern void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, int oparg); extern void _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, int oparg); +extern void _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr); /* Deallocator function for static codeobjects used in deepfreeze.py */ extern void _PyStaticCode_Dealloc(PyCodeObject *co); diff --git a/Include/internal/pycore_list.h b/Include/internal/pycore_list.h index 860dce1fd5d393..7721f6c2e222a0 100644 --- a/Include/internal/pycore_list.h +++ b/Include/internal/pycore_list.h @@ -56,6 +56,12 @@ _PyList_AppendTakeRef(PyListObject *self, PyObject *newitem) return _PyList_AppendTakeRefListResize(self, newitem); } +typedef struct { + PyObject_HEAD + Py_ssize_t it_index; + PyListObject *it_seq; /* Set to NULL when iterator is exhausted */ +} _PyListIterObject; + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_range.h b/Include/internal/pycore_range.h new file mode 100644 index 00000000000000..809e89a1e01b60 --- /dev/null +++ b/Include/internal/pycore_range.h @@ -0,0 +1,22 @@ +#ifndef Py_INTERNAL_RANGE_H +#define Py_INTERNAL_RANGE_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +typedef struct { + PyObject_HEAD + long index; + long start; + long step; + long len; +} _PyRangeIterObject; + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_RANGE_H */ diff --git a/Include/opcode.h b/Include/opcode.h index 8db42380cedd11..322e7eddd0dff9 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -139,55 +139,58 @@ extern "C" { #define COMPARE_OP_FLOAT_JUMP 27 #define COMPARE_OP_INT_JUMP 28 #define COMPARE_OP_STR_JUMP 29 -#define JUMP_BACKWARD_QUICK 34 -#define LOAD_ATTR_ADAPTIVE 38 -#define LOAD_ATTR_INSTANCE_VALUE 39 -#define LOAD_ATTR_MODULE 40 -#define LOAD_ATTR_SLOT 41 -#define LOAD_ATTR_WITH_HINT 42 -#define LOAD_CONST__LOAD_FAST 43 -#define LOAD_FAST__LOAD_CONST 44 -#define LOAD_FAST__LOAD_FAST 45 -#define LOAD_GLOBAL_ADAPTIVE 46 -#define LOAD_GLOBAL_BUILTIN 47 -#define LOAD_GLOBAL_MODULE 48 -#define LOAD_METHOD_ADAPTIVE 55 -#define LOAD_METHOD_CLASS 56 -#define LOAD_METHOD_MODULE 57 -#define LOAD_METHOD_NO_DICT 58 -#define LOAD_METHOD_WITH_DICT 59 -#define LOAD_METHOD_WITH_VALUES 62 -#define PRECALL_ADAPTIVE 63 -#define PRECALL_BOUND_METHOD 64 -#define PRECALL_BUILTIN_CLASS 65 -#define PRECALL_BUILTIN_FAST_WITH_KEYWORDS 66 -#define PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 67 -#define PRECALL_NO_KW_BUILTIN_FAST 72 -#define PRECALL_NO_KW_BUILTIN_O 73 -#define PRECALL_NO_KW_ISINSTANCE 76 -#define PRECALL_NO_KW_LEN 77 -#define PRECALL_NO_KW_LIST_APPEND 78 -#define PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST 79 -#define PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 80 -#define PRECALL_NO_KW_METHOD_DESCRIPTOR_O 81 -#define PRECALL_NO_KW_STR_1 113 -#define PRECALL_NO_KW_TUPLE_1 121 -#define PRECALL_NO_KW_TYPE_1 127 -#define PRECALL_PYFUNC 141 -#define RESUME_QUICK 143 -#define STORE_ATTR_ADAPTIVE 150 -#define STORE_ATTR_INSTANCE_VALUE 153 -#define STORE_ATTR_SLOT 154 -#define STORE_ATTR_WITH_HINT 158 -#define STORE_FAST__LOAD_FAST 159 -#define STORE_FAST__STORE_FAST 161 -#define STORE_SUBSCR_ADAPTIVE 167 -#define STORE_SUBSCR_DICT 168 -#define STORE_SUBSCR_LIST_INT 169 -#define UNPACK_SEQUENCE_ADAPTIVE 170 -#define UNPACK_SEQUENCE_LIST 177 -#define UNPACK_SEQUENCE_TUPLE 178 -#define UNPACK_SEQUENCE_TWO_TUPLE 179 +#define FOR_ITER_ADAPTIVE 34 +#define FOR_ITER_LIST 38 +#define FOR_ITER_RANGE 39 +#define JUMP_BACKWARD_QUICK 40 +#define LOAD_ATTR_ADAPTIVE 41 +#define LOAD_ATTR_INSTANCE_VALUE 42 +#define LOAD_ATTR_MODULE 43 +#define LOAD_ATTR_SLOT 44 +#define LOAD_ATTR_WITH_HINT 45 +#define LOAD_CONST__LOAD_FAST 46 +#define LOAD_FAST__LOAD_CONST 47 +#define LOAD_FAST__LOAD_FAST 48 +#define LOAD_GLOBAL_ADAPTIVE 55 +#define LOAD_GLOBAL_BUILTIN 56 +#define LOAD_GLOBAL_MODULE 57 +#define LOAD_METHOD_ADAPTIVE 58 +#define LOAD_METHOD_CLASS 59 +#define LOAD_METHOD_MODULE 62 +#define LOAD_METHOD_NO_DICT 63 +#define LOAD_METHOD_WITH_DICT 64 +#define LOAD_METHOD_WITH_VALUES 65 +#define PRECALL_ADAPTIVE 66 +#define PRECALL_BOUND_METHOD 67 +#define PRECALL_BUILTIN_CLASS 72 +#define PRECALL_BUILTIN_FAST_WITH_KEYWORDS 73 +#define PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 76 +#define PRECALL_NO_KW_BUILTIN_FAST 77 +#define PRECALL_NO_KW_BUILTIN_O 78 +#define PRECALL_NO_KW_ISINSTANCE 79 +#define PRECALL_NO_KW_LEN 80 +#define PRECALL_NO_KW_LIST_APPEND 81 +#define PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST 113 +#define PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 121 +#define PRECALL_NO_KW_METHOD_DESCRIPTOR_O 127 +#define PRECALL_NO_KW_STR_1 141 +#define PRECALL_NO_KW_TUPLE_1 143 +#define PRECALL_NO_KW_TYPE_1 150 +#define PRECALL_PYFUNC 153 +#define RESUME_QUICK 154 +#define STORE_ATTR_ADAPTIVE 158 +#define STORE_ATTR_INSTANCE_VALUE 159 +#define STORE_ATTR_SLOT 161 +#define STORE_ATTR_WITH_HINT 167 +#define STORE_FAST__LOAD_FAST 168 +#define STORE_FAST__STORE_FAST 169 +#define STORE_SUBSCR_ADAPTIVE 170 +#define STORE_SUBSCR_DICT 177 +#define STORE_SUBSCR_LIST_INT 178 +#define UNPACK_SEQUENCE_ADAPTIVE 179 +#define UNPACK_SEQUENCE_LIST 180 +#define UNPACK_SEQUENCE_TUPLE 181 +#define UNPACK_SEQUENCE_TWO_TUPLE 182 #define DO_TRACING 255 extern const uint8_t _PyOpcode_Caches[256]; @@ -220,6 +223,7 @@ const uint8_t _PyOpcode_Caches[256] = { [BINARY_SUBSCR] = 4, [STORE_SUBSCR] = 1, [UNPACK_SEQUENCE] = 1, + [FOR_ITER] = 1, [STORE_ATTR] = 4, [LOAD_ATTR] = 4, [COMPARE_OP] = 2, @@ -285,6 +289,9 @@ const uint8_t _PyOpcode_Deopt[256] = { [EXTENDED_ARG] = EXTENDED_ARG, [FORMAT_VALUE] = FORMAT_VALUE, [FOR_ITER] = FOR_ITER, + [FOR_ITER_ADAPTIVE] = FOR_ITER, + [FOR_ITER_LIST] = FOR_ITER, + [FOR_ITER_RANGE] = FOR_ITER, [GET_AITER] = GET_AITER, [GET_ANEXT] = GET_ANEXT, [GET_AWAITABLE] = GET_AWAITABLE, @@ -482,10 +489,13 @@ static const char *const _PyOpcode_OpName[256] = { [MATCH_MAPPING] = "MATCH_MAPPING", [MATCH_SEQUENCE] = "MATCH_SEQUENCE", [MATCH_KEYS] = "MATCH_KEYS", - [JUMP_BACKWARD_QUICK] = "JUMP_BACKWARD_QUICK", + [FOR_ITER_ADAPTIVE] = "FOR_ITER_ADAPTIVE", [PUSH_EXC_INFO] = "PUSH_EXC_INFO", [CHECK_EXC_MATCH] = "CHECK_EXC_MATCH", [CHECK_EG_MATCH] = "CHECK_EG_MATCH", + [FOR_ITER_LIST] = "FOR_ITER_LIST", + [FOR_ITER_RANGE] = "FOR_ITER_RANGE", + [JUMP_BACKWARD_QUICK] = "JUMP_BACKWARD_QUICK", [LOAD_ATTR_ADAPTIVE] = "LOAD_ATTR_ADAPTIVE", [LOAD_ATTR_INSTANCE_VALUE] = "LOAD_ATTR_INSTANCE_VALUE", [LOAD_ATTR_MODULE] = "LOAD_ATTR_MODULE", @@ -494,42 +504,39 @@ static const char *const _PyOpcode_OpName[256] = { [LOAD_CONST__LOAD_FAST] = "LOAD_CONST__LOAD_FAST", [LOAD_FAST__LOAD_CONST] = "LOAD_FAST__LOAD_CONST", [LOAD_FAST__LOAD_FAST] = "LOAD_FAST__LOAD_FAST", - [LOAD_GLOBAL_ADAPTIVE] = "LOAD_GLOBAL_ADAPTIVE", - [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", - [LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE", [WITH_EXCEPT_START] = "WITH_EXCEPT_START", [GET_AITER] = "GET_AITER", [GET_ANEXT] = "GET_ANEXT", [BEFORE_ASYNC_WITH] = "BEFORE_ASYNC_WITH", [BEFORE_WITH] = "BEFORE_WITH", [END_ASYNC_FOR] = "END_ASYNC_FOR", + [LOAD_GLOBAL_ADAPTIVE] = "LOAD_GLOBAL_ADAPTIVE", + [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", + [LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE", [LOAD_METHOD_ADAPTIVE] = "LOAD_METHOD_ADAPTIVE", [LOAD_METHOD_CLASS] = "LOAD_METHOD_CLASS", + [STORE_SUBSCR] = "STORE_SUBSCR", + [DELETE_SUBSCR] = "DELETE_SUBSCR", [LOAD_METHOD_MODULE] = "LOAD_METHOD_MODULE", [LOAD_METHOD_NO_DICT] = "LOAD_METHOD_NO_DICT", [LOAD_METHOD_WITH_DICT] = "LOAD_METHOD_WITH_DICT", - [STORE_SUBSCR] = "STORE_SUBSCR", - [DELETE_SUBSCR] = "DELETE_SUBSCR", [LOAD_METHOD_WITH_VALUES] = "LOAD_METHOD_WITH_VALUES", [PRECALL_ADAPTIVE] = "PRECALL_ADAPTIVE", [PRECALL_BOUND_METHOD] = "PRECALL_BOUND_METHOD", - [PRECALL_BUILTIN_CLASS] = "PRECALL_BUILTIN_CLASS", - [PRECALL_BUILTIN_FAST_WITH_KEYWORDS] = "PRECALL_BUILTIN_FAST_WITH_KEYWORDS", - [PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", [GET_ITER] = "GET_ITER", [GET_YIELD_FROM_ITER] = "GET_YIELD_FROM_ITER", [PRINT_EXPR] = "PRINT_EXPR", [LOAD_BUILD_CLASS] = "LOAD_BUILD_CLASS", - [PRECALL_NO_KW_BUILTIN_FAST] = "PRECALL_NO_KW_BUILTIN_FAST", - [PRECALL_NO_KW_BUILTIN_O] = "PRECALL_NO_KW_BUILTIN_O", + [PRECALL_BUILTIN_CLASS] = "PRECALL_BUILTIN_CLASS", + [PRECALL_BUILTIN_FAST_WITH_KEYWORDS] = "PRECALL_BUILTIN_FAST_WITH_KEYWORDS", [LOAD_ASSERTION_ERROR] = "LOAD_ASSERTION_ERROR", [RETURN_GENERATOR] = "RETURN_GENERATOR", + [PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", + [PRECALL_NO_KW_BUILTIN_FAST] = "PRECALL_NO_KW_BUILTIN_FAST", + [PRECALL_NO_KW_BUILTIN_O] = "PRECALL_NO_KW_BUILTIN_O", [PRECALL_NO_KW_ISINSTANCE] = "PRECALL_NO_KW_ISINSTANCE", [PRECALL_NO_KW_LEN] = "PRECALL_NO_KW_LEN", [PRECALL_NO_KW_LIST_APPEND] = "PRECALL_NO_KW_LIST_APPEND", - [PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST] = "PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST", - [PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = "PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS", - [PRECALL_NO_KW_METHOD_DESCRIPTOR_O] = "PRECALL_NO_KW_METHOD_DESCRIPTOR_O", [LIST_TO_TUPLE] = "LIST_TO_TUPLE", [RETURN_VALUE] = "RETURN_VALUE", [IMPORT_STAR] = "IMPORT_STAR", @@ -561,7 +568,7 @@ static const char *const _PyOpcode_OpName[256] = { [JUMP_FORWARD] = "JUMP_FORWARD", [JUMP_IF_FALSE_OR_POP] = "JUMP_IF_FALSE_OR_POP", [JUMP_IF_TRUE_OR_POP] = "JUMP_IF_TRUE_OR_POP", - [PRECALL_NO_KW_STR_1] = "PRECALL_NO_KW_STR_1", + [PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST] = "PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST", [POP_JUMP_FORWARD_IF_FALSE] = "POP_JUMP_FORWARD_IF_FALSE", [POP_JUMP_FORWARD_IF_TRUE] = "POP_JUMP_FORWARD_IF_TRUE", [LOAD_GLOBAL] = "LOAD_GLOBAL", @@ -569,13 +576,13 @@ static const char *const _PyOpcode_OpName[256] = { [CONTAINS_OP] = "CONTAINS_OP", [RERAISE] = "RERAISE", [COPY] = "COPY", - [PRECALL_NO_KW_TUPLE_1] = "PRECALL_NO_KW_TUPLE_1", + [PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = "PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS", [BINARY_OP] = "BINARY_OP", [SEND] = "SEND", [LOAD_FAST] = "LOAD_FAST", [STORE_FAST] = "STORE_FAST", [DELETE_FAST] = "DELETE_FAST", - [PRECALL_NO_KW_TYPE_1] = "PRECALL_NO_KW_TYPE_1", + [PRECALL_NO_KW_METHOD_DESCRIPTOR_O] = "PRECALL_NO_KW_METHOD_DESCRIPTOR_O", [POP_JUMP_FORWARD_IF_NOT_NONE] = "POP_JUMP_FORWARD_IF_NOT_NONE", [POP_JUMP_FORWARD_IF_NONE] = "POP_JUMP_FORWARD_IF_NONE", [RAISE_VARARGS] = "RAISE_VARARGS", @@ -589,48 +596,48 @@ static const char *const _PyOpcode_OpName[256] = { [STORE_DEREF] = "STORE_DEREF", [DELETE_DEREF] = "DELETE_DEREF", [JUMP_BACKWARD] = "JUMP_BACKWARD", - [PRECALL_PYFUNC] = "PRECALL_PYFUNC", + [PRECALL_NO_KW_STR_1] = "PRECALL_NO_KW_STR_1", [CALL_FUNCTION_EX] = "CALL_FUNCTION_EX", - [RESUME_QUICK] = "RESUME_QUICK", + [PRECALL_NO_KW_TUPLE_1] = "PRECALL_NO_KW_TUPLE_1", [EXTENDED_ARG] = "EXTENDED_ARG", [LIST_APPEND] = "LIST_APPEND", [SET_ADD] = "SET_ADD", [MAP_ADD] = "MAP_ADD", [LOAD_CLASSDEREF] = "LOAD_CLASSDEREF", [COPY_FREE_VARS] = "COPY_FREE_VARS", - [STORE_ATTR_ADAPTIVE] = "STORE_ATTR_ADAPTIVE", + [PRECALL_NO_KW_TYPE_1] = "PRECALL_NO_KW_TYPE_1", [RESUME] = "RESUME", [MATCH_CLASS] = "MATCH_CLASS", - [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", - [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", + [PRECALL_PYFUNC] = "PRECALL_PYFUNC", + [RESUME_QUICK] = "RESUME_QUICK", [FORMAT_VALUE] = "FORMAT_VALUE", [BUILD_CONST_KEY_MAP] = "BUILD_CONST_KEY_MAP", [BUILD_STRING] = "BUILD_STRING", - [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT", - [STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST", + [STORE_ATTR_ADAPTIVE] = "STORE_ATTR_ADAPTIVE", + [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", [LOAD_METHOD] = "LOAD_METHOD", - [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST", + [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", [LIST_EXTEND] = "LIST_EXTEND", [SET_UPDATE] = "SET_UPDATE", [DICT_MERGE] = "DICT_MERGE", [DICT_UPDATE] = "DICT_UPDATE", [PRECALL] = "PRECALL", + [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT", + [STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST", + [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST", [STORE_SUBSCR_ADAPTIVE] = "STORE_SUBSCR_ADAPTIVE", - [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT", - [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT", - [UNPACK_SEQUENCE_ADAPTIVE] = "UNPACK_SEQUENCE_ADAPTIVE", [CALL] = "CALL", [KW_NAMES] = "KW_NAMES", [POP_JUMP_BACKWARD_IF_NOT_NONE] = "POP_JUMP_BACKWARD_IF_NOT_NONE", [POP_JUMP_BACKWARD_IF_NONE] = "POP_JUMP_BACKWARD_IF_NONE", [POP_JUMP_BACKWARD_IF_FALSE] = "POP_JUMP_BACKWARD_IF_FALSE", [POP_JUMP_BACKWARD_IF_TRUE] = "POP_JUMP_BACKWARD_IF_TRUE", + [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT", + [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT", + [UNPACK_SEQUENCE_ADAPTIVE] = "UNPACK_SEQUENCE_ADAPTIVE", [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST", [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE", [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE", - [180] = "<180>", - [181] = "<181>", - [182] = "<182>", [183] = "<183>", [184] = "<184>", [185] = "<185>", diff --git a/Lib/opcode.py b/Lib/opcode.py index 9ee06831c37687..fc3f31d14837f7 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -111,7 +111,7 @@ def jabs_op(name, op, entries=0): name_op('STORE_NAME', 90) # Index in name list name_op('DELETE_NAME', 91) # "" def_op('UNPACK_SEQUENCE', 92, 1) # Number of tuple items -jrel_op('FOR_ITER', 93) +jrel_op('FOR_ITER', 93, 1) def_op('UNPACK_EX', 94) name_op('STORE_ATTR', 95, 4) # Index in name list name_op('DELETE_ATTR', 96) # "" @@ -264,6 +264,11 @@ def jabs_op(name, op, entries=0): "COMPARE_OP_INT_JUMP", "COMPARE_OP_STR_JUMP", ], + "FOR_ITER": [ + "FOR_ITER_ADAPTIVE", + "FOR_ITER_LIST", + "FOR_ITER_RANGE", + ], "JUMP_BACKWARD": [ "JUMP_BACKWARD_QUICK", ], diff --git a/Makefile.pre.in b/Makefile.pre.in index f6c8c72bbc2c3c..bab93a34af7366 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1612,6 +1612,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_pylifecycle.h \ $(srcdir)/Include/internal/pycore_pymem.h \ $(srcdir)/Include/internal/pycore_pystate.h \ + $(srcdir)/Include/internal/pycore_range.h \ $(srcdir)/Include/internal/pycore_runtime.h \ $(srcdir)/Include/internal/pycore_runtime_init.h \ $(srcdir)/Include/internal/pycore_sliceobject.h \ diff --git a/Objects/listobject.c b/Objects/listobject.c index ccb9b91ba930d7..6346246b3db644 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -3,7 +3,7 @@ #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() #include "pycore_interp.h" // PyInterpreterState.list -#include "pycore_list.h" // struct _Py_list_state +#include "pycore_list.h" // struct _Py_list_state, _PyListIterObject #include "pycore_object.h" // _PyObject_GC_TRACK() #include "pycore_tuple.h" // _PyTuple_FromArray() #include @@ -3178,19 +3178,13 @@ PyTypeObject PyList_Type = { /*********************** List Iterator **************************/ -typedef struct { - PyObject_HEAD - Py_ssize_t it_index; - PyListObject *it_seq; /* Set to NULL when iterator is exhausted */ -} listiterobject; - -static void listiter_dealloc(listiterobject *); -static int listiter_traverse(listiterobject *, visitproc, void *); -static PyObject *listiter_next(listiterobject *); -static PyObject *listiter_len(listiterobject *, PyObject *); +static void listiter_dealloc(_PyListIterObject *); +static int listiter_traverse(_PyListIterObject *, visitproc, void *); +static PyObject *listiter_next(_PyListIterObject *); +static PyObject *listiter_len(_PyListIterObject *, PyObject *); static PyObject *listiter_reduce_general(void *_it, int forward); -static PyObject *listiter_reduce(listiterobject *, PyObject *); -static PyObject *listiter_setstate(listiterobject *, PyObject *state); +static PyObject *listiter_reduce(_PyListIterObject *, PyObject *); +static PyObject *listiter_setstate(_PyListIterObject *, PyObject *state); PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); @@ -3206,7 +3200,7 @@ static PyMethodDef listiter_methods[] = { PyTypeObject PyListIter_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "list_iterator", /* tp_name */ - sizeof(listiterobject), /* tp_basicsize */ + sizeof(_PyListIterObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)listiter_dealloc, /* tp_dealloc */ @@ -3240,13 +3234,13 @@ PyTypeObject PyListIter_Type = { static PyObject * list_iter(PyObject *seq) { - listiterobject *it; + _PyListIterObject *it; if (!PyList_Check(seq)) { PyErr_BadInternalCall(); return NULL; } - it = PyObject_GC_New(listiterobject, &PyListIter_Type); + it = PyObject_GC_New(_PyListIterObject, &PyListIter_Type); if (it == NULL) return NULL; it->it_index = 0; @@ -3257,7 +3251,7 @@ list_iter(PyObject *seq) } static void -listiter_dealloc(listiterobject *it) +listiter_dealloc(_PyListIterObject *it) { _PyObject_GC_UNTRACK(it); Py_XDECREF(it->it_seq); @@ -3265,14 +3259,14 @@ listiter_dealloc(listiterobject *it) } static int -listiter_traverse(listiterobject *it, visitproc visit, void *arg) +listiter_traverse(_PyListIterObject *it, visitproc visit, void *arg) { Py_VISIT(it->it_seq); return 0; } static PyObject * -listiter_next(listiterobject *it) +listiter_next(_PyListIterObject *it) { PyListObject *seq; PyObject *item; @@ -3296,7 +3290,7 @@ listiter_next(listiterobject *it) } static PyObject * -listiter_len(listiterobject *it, PyObject *Py_UNUSED(ignored)) +listiter_len(_PyListIterObject *it, PyObject *Py_UNUSED(ignored)) { Py_ssize_t len; if (it->it_seq) { @@ -3308,13 +3302,13 @@ listiter_len(listiterobject *it, PyObject *Py_UNUSED(ignored)) } static PyObject * -listiter_reduce(listiterobject *it, PyObject *Py_UNUSED(ignored)) +listiter_reduce(_PyListIterObject *it, PyObject *Py_UNUSED(ignored)) { return listiter_reduce_general(it, 1); } static PyObject * -listiter_setstate(listiterobject *it, PyObject *state) +listiter_setstate(_PyListIterObject *it, PyObject *state) { Py_ssize_t index = PyLong_AsSsize_t(state); if (index == -1 && PyErr_Occurred()) @@ -3489,7 +3483,7 @@ listiter_reduce_general(void *_it, int forward) /* the objects are not the same, index is of different types! */ if (forward) { - listiterobject *it = (listiterobject *)_it; + _PyListIterObject *it = (_PyListIterObject *)_it; if (it->it_seq) { return Py_BuildValue("N(O)n", _PyEval_GetBuiltin(&_Py_ID(iter)), it->it_seq, it->it_index); diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 5d583b2edf0e94..f0b06de1c7d2a0 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -2,6 +2,7 @@ #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() +#include "pycore_range.h" #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_tuple.h" // _PyTuple_ITEMS() #include "structmember.h" // PyMemberDef @@ -762,16 +763,8 @@ PyTypeObject PyRange_Type = { in the normal case, but possible for any numeric value. */ -typedef struct { - PyObject_HEAD - long index; - long start; - long step; - long len; -} rangeiterobject; - static PyObject * -rangeiter_next(rangeiterobject *r) +rangeiter_next(_PyRangeIterObject *r) { if (r->index < r->len) /* cast to unsigned to avoid possible signed overflow @@ -782,7 +775,7 @@ rangeiter_next(rangeiterobject *r) } static PyObject * -rangeiter_len(rangeiterobject *r, PyObject *Py_UNUSED(ignored)) +rangeiter_len(_PyRangeIterObject *r, PyObject *Py_UNUSED(ignored)) { return PyLong_FromLong(r->len - r->index); } @@ -791,7 +784,7 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); static PyObject * -rangeiter_reduce(rangeiterobject *r, PyObject *Py_UNUSED(ignored)) +rangeiter_reduce(_PyRangeIterObject *r, PyObject *Py_UNUSED(ignored)) { PyObject *start=NULL, *stop=NULL, *step=NULL; PyObject *range; @@ -821,7 +814,7 @@ rangeiter_reduce(rangeiterobject *r, PyObject *Py_UNUSED(ignored)) } static PyObject * -rangeiter_setstate(rangeiterobject *r, PyObject *state) +rangeiter_setstate(_PyRangeIterObject *r, PyObject *state) { long index = PyLong_AsLong(state); if (index == -1 && PyErr_Occurred()) @@ -850,8 +843,8 @@ static PyMethodDef rangeiter_methods[] = { PyTypeObject PyRangeIter_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - "range_iterator", /* tp_name */ - sizeof(rangeiterobject), /* tp_basicsize */ + "range_iterator", /* tp_name */ + sizeof(_PyRangeIterObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)PyObject_Del, /* tp_dealloc */ @@ -915,7 +908,7 @@ get_len_of_range(long lo, long hi, long step) static PyObject * fast_range_iter(long start, long stop, long step, long len) { - rangeiterobject *it = PyObject_New(rangeiterobject, &PyRangeIter_Type); + _PyRangeIterObject *it = PyObject_New(_PyRangeIterObject, &PyRangeIter_Type); if (it == NULL) return NULL; it->start = start; diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index cbd39368601208..ffb5a91dd54a79 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -234,6 +234,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 70af3052221708..fae9bc0eb0d1c0 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -606,6 +606,9 @@ Include\internal + + Include\internal + Include\internal diff --git a/Python/ceval.c b/Python/ceval.c index d358a3134bc63a..0329312ee7f8a9 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -19,6 +19,7 @@ #include "pycore_pylifecycle.h" // _PyErr_Print() #include "pycore_pymem.h" // _PyMem_IsPtrFreed() #include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "pycore_range.h" // _PyRangeIterObject #include "pycore_sysmodule.h" // _PySys_Audit() #include "pycore_tuple.h" // _PyTuple_ITEMS() #include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS @@ -4325,16 +4326,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PREDICTED(FOR_ITER); /* before: [iter]; after: [iter, iter()] *or* [] */ PyObject *iter = TOP(); -#ifdef Py_STATS - extern int _PySpecialization_ClassifyIterator(PyObject *); - _py_stats.opcode_stats[FOR_ITER].specialization.failure++; - _py_stats.opcode_stats[FOR_ITER].specialization.failure_kinds[_PySpecialization_ClassifyIterator(iter)]++; -#endif PyObject *next = (*Py_TYPE(iter)->tp_iternext)(iter); if (next != NULL) { PUSH(next); PREDICT(STORE_FAST); PREDICT(UNPACK_SEQUENCE); + JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); DISPATCH(); } if (_PyErr_Occurred(tstate)) { @@ -4346,13 +4343,67 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } _PyErr_Clear(tstate); } + iterator_exhausted_no_error: /* iterator ended normally */ - STACK_SHRINK(1); - Py_DECREF(iter); - JUMPBY(oparg); + Py_DECREF(POP()); + JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg); DISPATCH(); } + TARGET(FOR_ITER_ADAPTIVE) { + assert(cframe.use_tracing == 0); + _PyForIterCache *cache = (_PyForIterCache *)next_instr; + if (cache->counter == 0) { + next_instr--; + _Py_Specialize_ForIter(TOP(), next_instr); + DISPATCH(); + } + else { + STAT_INC(FOR_ITER, deferred); + cache->counter--; + JUMP_TO_INSTRUCTION(FOR_ITER); + } + } + + TARGET(FOR_ITER_LIST) { + assert(cframe.use_tracing == 0); + _PyListIterObject *it = (_PyListIterObject *)TOP(); + DEOPT_IF(Py_TYPE(it) != &PyListIter_Type, JUMP_BACKWARD); + STAT_INC(JUMP_BACKWARD, hit); + PyListObject *seq = it->it_seq; + if (seq == NULL) { + goto iterator_exhausted_no_error; + } + if (it->it_index < PyList_GET_SIZE(seq)) { + PyObject *next = PyList_GET_ITEM(seq, it->it_index++); + Py_INCREF(next); + PUSH(next); + JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); + NOTRACE_DISPATCH(); + } + it->it_seq = NULL; + Py_DECREF(seq); + goto iterator_exhausted_no_error; + } + + TARGET(FOR_ITER_RANGE) { + assert(cframe.use_tracing == 0); + _PyRangeIterObject *r = (_PyRangeIterObject *)TOP(); + DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER); + STAT_INC(FOR_ITER, hit); + if (r->index < r->len) { + PyObject *res = PyLong_FromLong( + (long)(r->start + (unsigned long)(r->index++) * r->step)); + if (res == NULL) { + goto error; + } + PUSH(res); + JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); + NOTRACE_DISPATCH(); + } + goto iterator_exhausted_no_error; + } + TARGET(BEFORE_ASYNC_WITH) { PyObject *mgr = TOP(); PyObject *res; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 5268c4f2a27750..92c626bbf205c2 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -33,10 +33,13 @@ static void *opcode_targets[256] = { &&TARGET_MATCH_MAPPING, &&TARGET_MATCH_SEQUENCE, &&TARGET_MATCH_KEYS, - &&TARGET_JUMP_BACKWARD_QUICK, + &&TARGET_FOR_ITER_ADAPTIVE, &&TARGET_PUSH_EXC_INFO, &&TARGET_CHECK_EXC_MATCH, &&TARGET_CHECK_EG_MATCH, + &&TARGET_FOR_ITER_LIST, + &&TARGET_FOR_ITER_RANGE, + &&TARGET_JUMP_BACKWARD_QUICK, &&TARGET_LOAD_ATTR_ADAPTIVE, &&TARGET_LOAD_ATTR_INSTANCE_VALUE, &&TARGET_LOAD_ATTR_MODULE, @@ -45,42 +48,39 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_CONST__LOAD_FAST, &&TARGET_LOAD_FAST__LOAD_CONST, &&TARGET_LOAD_FAST__LOAD_FAST, - &&TARGET_LOAD_GLOBAL_ADAPTIVE, - &&TARGET_LOAD_GLOBAL_BUILTIN, - &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_WITH_EXCEPT_START, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, &&TARGET_BEFORE_ASYNC_WITH, &&TARGET_BEFORE_WITH, &&TARGET_END_ASYNC_FOR, + &&TARGET_LOAD_GLOBAL_ADAPTIVE, + &&TARGET_LOAD_GLOBAL_BUILTIN, + &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_LOAD_METHOD_ADAPTIVE, &&TARGET_LOAD_METHOD_CLASS, + &&TARGET_STORE_SUBSCR, + &&TARGET_DELETE_SUBSCR, &&TARGET_LOAD_METHOD_MODULE, &&TARGET_LOAD_METHOD_NO_DICT, &&TARGET_LOAD_METHOD_WITH_DICT, - &&TARGET_STORE_SUBSCR, - &&TARGET_DELETE_SUBSCR, &&TARGET_LOAD_METHOD_WITH_VALUES, &&TARGET_PRECALL_ADAPTIVE, &&TARGET_PRECALL_BOUND_METHOD, - &&TARGET_PRECALL_BUILTIN_CLASS, - &&TARGET_PRECALL_BUILTIN_FAST_WITH_KEYWORDS, - &&TARGET_PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, &&TARGET_LOAD_BUILD_CLASS, - &&TARGET_PRECALL_NO_KW_BUILTIN_FAST, - &&TARGET_PRECALL_NO_KW_BUILTIN_O, + &&TARGET_PRECALL_BUILTIN_CLASS, + &&TARGET_PRECALL_BUILTIN_FAST_WITH_KEYWORDS, &&TARGET_LOAD_ASSERTION_ERROR, &&TARGET_RETURN_GENERATOR, + &&TARGET_PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, + &&TARGET_PRECALL_NO_KW_BUILTIN_FAST, + &&TARGET_PRECALL_NO_KW_BUILTIN_O, &&TARGET_PRECALL_NO_KW_ISINSTANCE, &&TARGET_PRECALL_NO_KW_LEN, &&TARGET_PRECALL_NO_KW_LIST_APPEND, - &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST, - &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, - &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_O, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, @@ -112,7 +112,7 @@ static void *opcode_targets[256] = { &&TARGET_JUMP_FORWARD, &&TARGET_JUMP_IF_FALSE_OR_POP, &&TARGET_JUMP_IF_TRUE_OR_POP, - &&TARGET_PRECALL_NO_KW_STR_1, + &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST, &&TARGET_POP_JUMP_FORWARD_IF_FALSE, &&TARGET_POP_JUMP_FORWARD_IF_TRUE, &&TARGET_LOAD_GLOBAL, @@ -120,13 +120,13 @@ static void *opcode_targets[256] = { &&TARGET_CONTAINS_OP, &&TARGET_RERAISE, &&TARGET_COPY, - &&TARGET_PRECALL_NO_KW_TUPLE_1, + &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, &&TARGET_BINARY_OP, &&TARGET_SEND, &&TARGET_LOAD_FAST, &&TARGET_STORE_FAST, &&TARGET_DELETE_FAST, - &&TARGET_PRECALL_NO_KW_TYPE_1, + &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_O, &&TARGET_POP_JUMP_FORWARD_IF_NOT_NONE, &&TARGET_POP_JUMP_FORWARD_IF_NONE, &&TARGET_RAISE_VARARGS, @@ -140,42 +140,45 @@ static void *opcode_targets[256] = { &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, &&TARGET_JUMP_BACKWARD, - &&TARGET_PRECALL_PYFUNC, + &&TARGET_PRECALL_NO_KW_STR_1, &&TARGET_CALL_FUNCTION_EX, - &&TARGET_RESUME_QUICK, + &&TARGET_PRECALL_NO_KW_TUPLE_1, &&TARGET_EXTENDED_ARG, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, &&TARGET_MAP_ADD, &&TARGET_LOAD_CLASSDEREF, &&TARGET_COPY_FREE_VARS, - &&TARGET_STORE_ATTR_ADAPTIVE, + &&TARGET_PRECALL_NO_KW_TYPE_1, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, - &&TARGET_STORE_ATTR_INSTANCE_VALUE, - &&TARGET_STORE_ATTR_SLOT, + &&TARGET_PRECALL_PYFUNC, + &&TARGET_RESUME_QUICK, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, - &&TARGET_STORE_ATTR_WITH_HINT, - &&TARGET_STORE_FAST__LOAD_FAST, + &&TARGET_STORE_ATTR_ADAPTIVE, + &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_LOAD_METHOD, - &&TARGET_STORE_FAST__STORE_FAST, + &&TARGET_STORE_ATTR_SLOT, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, &&TARGET_DICT_UPDATE, &&TARGET_PRECALL, + &&TARGET_STORE_ATTR_WITH_HINT, + &&TARGET_STORE_FAST__LOAD_FAST, + &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_STORE_SUBSCR_ADAPTIVE, - &&TARGET_STORE_SUBSCR_DICT, - &&TARGET_STORE_SUBSCR_LIST_INT, - &&TARGET_UNPACK_SEQUENCE_ADAPTIVE, &&TARGET_CALL, &&TARGET_KW_NAMES, &&TARGET_POP_JUMP_BACKWARD_IF_NOT_NONE, &&TARGET_POP_JUMP_BACKWARD_IF_NONE, &&TARGET_POP_JUMP_BACKWARD_IF_FALSE, &&TARGET_POP_JUMP_BACKWARD_IF_TRUE, + &&TARGET_STORE_SUBSCR_DICT, + &&TARGET_STORE_SUBSCR_LIST_INT, + &&TARGET_UNPACK_SEQUENCE_ADAPTIVE, &&TARGET_UNPACK_SEQUENCE_LIST, &&TARGET_UNPACK_SEQUENCE_TUPLE, &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, @@ -251,8 +254,5 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_DO_TRACING }; diff --git a/Python/specialize.c b/Python/specialize.c index 3a8b768549c63d..1b12d6145a681e 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -29,6 +29,7 @@ uint8_t _PyOpcode_Adaptive[256] = { [BINARY_OP] = BINARY_OP_ADAPTIVE, [COMPARE_OP] = COMPARE_OP_ADAPTIVE, [UNPACK_SEQUENCE] = UNPACK_SEQUENCE_ADAPTIVE, + [FOR_ITER] = FOR_ITER_ADAPTIVE, }; Py_ssize_t _Py_QuickenedCount = 0; @@ -2056,3 +2057,31 @@ int } #endif + +void +_Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr) +{ + assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER); + _PyForIterCache *cache = (_PyForIterCache *)(instr + 1); + PyTypeObject *tp = Py_TYPE(iter); + if (tp == &PyListIter_Type) { + _Py_SET_OPCODE(*instr, FOR_ITER_LIST); + goto success; + } + else if (tp == &PyRangeIter_Type) { + _Py_SET_OPCODE(*instr, FOR_ITER_RANGE); + goto success; + } + else { + SPECIALIZATION_FAIL(JUMP_BACKWARD, + _PySpecialization_ClassifyIterator(iter)); + goto failure; + } +failure: + STAT_INC(FOR_ITER, failure); + cache->counter = ADAPTIVE_CACHE_BACKOFF; + return; +success: + STAT_INC(FOR_ITER, success); + cache->counter = initial_counter_value(); +} From 3b5ce1ed103d010bcf0b0cdca245f8ac4d324a26 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Sat, 16 Apr 2022 21:34:18 -0400 Subject: [PATCH 02/24] bump magic --- Lib/importlib/_bootstrap_external.py | 2 +- Programs/test_frozenmain.h | 68 ++++++++++++++-------------- Python/ceval.c | 1 + 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 4eece8de24c3e9..fa3f17bb73d870 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -416,7 +416,7 @@ def _write_atomic(path, data, mode=0o666): # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # in PC/launcher.c must also be updated. -MAGIC_NUMBER = (3493).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3494).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index a3c09529116cc1..f20f6a86286501 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,7 +1,7 @@ // Auto-generated by Programs/freeze_test_frozenmain.py unsigned char M_test_frozenmain[] = { 227,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0, - 0,0,0,0,0,115,176,0,0,0,151,0,100,0,100,1, + 0,0,0,0,0,115,178,0,0,0,151,0,100,0,100,1, 108,0,90,0,100,0,100,1,108,1,90,1,2,0,101,2, 100,2,166,1,0,0,171,1,0,0,0,0,0,0,0,0, 1,0,2,0,101,2,100,3,101,0,106,3,0,0,0,0, @@ -9,38 +9,38 @@ unsigned char M_test_frozenmain[] = { 0,0,1,0,2,0,101,1,106,4,0,0,0,0,0,0, 0,0,166,0,0,0,171,0,0,0,0,0,0,0,0,0, 100,4,25,0,0,0,0,0,0,0,0,0,90,5,100,5, - 68,0,93,25,90,6,2,0,101,2,100,6,101,6,155,0, - 100,7,101,5,101,6,25,0,0,0,0,0,0,0,0,0, - 155,0,157,4,166,1,0,0,171,1,0,0,0,0,0,0, - 0,0,1,0,140,26,100,1,83,0,41,8,233,0,0,0, - 0,78,122,18,70,114,111,122,101,110,32,72,101,108,108,111, - 32,87,111,114,108,100,122,8,115,121,115,46,97,114,103,118, - 218,6,99,111,110,102,105,103,41,5,90,12,112,114,111,103, - 114,97,109,95,110,97,109,101,218,10,101,120,101,99,117,116, - 97,98,108,101,90,15,117,115,101,95,101,110,118,105,114,111, - 110,109,101,110,116,90,17,99,111,110,102,105,103,117,114,101, - 95,99,95,115,116,100,105,111,90,14,98,117,102,102,101,114, - 101,100,95,115,116,100,105,111,122,7,99,111,110,102,105,103, - 32,122,2,58,32,41,7,218,3,115,121,115,90,17,95,116, - 101,115,116,105,110,116,101,114,110,97,108,99,97,112,105,218, - 5,112,114,105,110,116,218,4,97,114,103,118,90,11,103,101, - 116,95,99,111,110,102,105,103,115,114,2,0,0,0,218,3, - 107,101,121,169,0,243,0,0,0,0,250,18,116,101,115,116, - 95,102,114,111,122,101,110,109,97,105,110,46,112,121,250,8, - 60,109,111,100,117,108,101,62,114,11,0,0,0,1,0,0, - 0,115,18,0,0,0,2,128,8,3,8,1,22,2,34,1, - 42,1,8,1,48,7,4,249,115,20,0,0,0,2,128,8, - 3,8,1,22,2,34,1,42,1,2,7,4,1,2,249,52, - 7,115,176,0,0,0,0,0,1,11,1,11,1,11,1,11, - 1,25,1,25,1,25,1,25,1,6,1,6,7,27,1,28, - 1,28,1,28,1,28,1,28,1,28,1,28,1,28,1,6, - 1,6,7,17,19,22,19,27,19,27,19,27,19,27,19,27, + 68,0,93,25,0,0,90,6,2,0,101,2,100,6,101,6, + 155,0,100,7,101,5,101,6,25,0,0,0,0,0,0,0, + 0,0,155,0,157,4,166,1,0,0,171,1,0,0,0,0, + 0,0,0,0,1,0,140,27,100,1,83,0,41,8,233,0, + 0,0,0,78,122,18,70,114,111,122,101,110,32,72,101,108, + 108,111,32,87,111,114,108,100,122,8,115,121,115,46,97,114, + 103,118,218,6,99,111,110,102,105,103,41,5,90,12,112,114, + 111,103,114,97,109,95,110,97,109,101,218,10,101,120,101,99, + 117,116,97,98,108,101,90,15,117,115,101,95,101,110,118,105, + 114,111,110,109,101,110,116,90,17,99,111,110,102,105,103,117, + 114,101,95,99,95,115,116,100,105,111,90,14,98,117,102,102, + 101,114,101,100,95,115,116,100,105,111,122,7,99,111,110,102, + 105,103,32,122,2,58,32,41,7,218,3,115,121,115,90,17, + 95,116,101,115,116,105,110,116,101,114,110,97,108,99,97,112, + 105,218,5,112,114,105,110,116,218,4,97,114,103,118,90,11, + 103,101,116,95,99,111,110,102,105,103,115,114,2,0,0,0, + 218,3,107,101,121,169,0,243,0,0,0,0,250,18,116,101, + 115,116,95,102,114,111,122,101,110,109,97,105,110,46,112,121, + 250,8,60,109,111,100,117,108,101,62,114,11,0,0,0,1, + 0,0,0,115,18,0,0,0,2,128,8,3,8,1,22,2, + 34,1,42,1,10,1,48,7,4,249,115,20,0,0,0,2, + 128,8,3,8,1,22,2,34,1,42,1,2,7,6,1,2, + 249,52,7,115,178,0,0,0,0,0,1,11,1,11,1,11, + 1,11,1,25,1,25,1,25,1,25,1,6,1,6,7,27, 1,28,1,28,1,28,1,28,1,28,1,28,1,28,1,28, - 10,39,10,27,10,39,10,39,10,39,10,39,10,39,10,41, - 10,41,10,41,10,41,10,41,10,41,10,41,42,50,10,51, - 10,51,10,51,10,51,10,51,1,7,12,2,1,42,1,42, - 5,8,5,10,5,10,11,41,21,24,11,41,11,41,28,34, - 35,38,28,39,28,39,28,39,28,39,28,39,11,41,11,41, - 5,42,5,42,5,42,5,42,5,42,5,42,5,42,5,42, - 5,42,1,42,1,42,114,9,0,0,0, + 1,6,1,6,7,17,19,22,19,27,19,27,19,27,19,27, + 19,27,1,28,1,28,1,28,1,28,1,28,1,28,1,28, + 1,28,10,39,10,27,10,39,10,39,10,39,10,39,10,39, + 10,41,10,41,10,41,10,41,10,41,10,41,10,41,42,50, + 10,51,10,51,10,51,10,51,10,51,1,7,12,2,1,42, + 1,42,1,42,5,8,5,10,5,10,11,41,21,24,11,41, + 11,41,28,34,35,38,28,39,28,39,28,39,28,39,28,39, + 11,41,11,41,5,42,5,42,5,42,5,42,5,42,5,42, + 5,42,5,42,5,42,1,42,1,42,114,9,0,0,0, }; diff --git a/Python/ceval.c b/Python/ceval.c index 0329312ee7f8a9..504049b8455295 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4345,6 +4345,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } iterator_exhausted_no_error: /* iterator ended normally */ + assert(!_PyErr_Occurred(tstate)); Py_DECREF(POP()); JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg); DISPATCH(); From 37269cf9edb1d37a503377ecea2d36249d2478b9 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Mon, 18 Apr 2022 00:47:32 -0400 Subject: [PATCH 03/24] NOTRACE_DISPATCH_SAME_OPARG --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/ceval.c b/Python/ceval.c index 5b69f1c47df59e..2ff2f9082e24c1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4364,7 +4364,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (cache->counter == 0) { next_instr--; _Py_Specialize_ForIter(TOP(), next_instr); - DISPATCH(); + NOTRACE_DISPATCH_SAME_OPARG(); } else { STAT_INC(FOR_ITER, deferred); From ea0a7ee540dd48ffd8301f3adb1a818ef0265a26 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Mon, 18 Apr 2022 03:31:40 -0400 Subject: [PATCH 04/24] Update mark_stacks --- Objects/frameobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/frameobject.c b/Objects/frameobject.c index dc4ef8bcda541f..324ea2dcaf0cc0 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -277,7 +277,7 @@ mark_stacks(PyCodeObject *code_obj, int len) { int64_t target_stack = pop_value(next_stack); stacks[i+1] = push_value(next_stack, Object); - j = get_arg(code, i) + i + 1; + j = get_arg(code, i) + 1 + INLINE_CACHE_ENTRIES_FOR_ITER + i; assert(j < len); assert(stacks[j] == UNINITIALIZED || stacks[j] == target_stack); stacks[j] = target_stack; From 075122828216ae4c26df7f2146a21b3a34fdc89a Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Tue, 19 Apr 2022 13:16:48 -0400 Subject: [PATCH 05/24] comment out assertions --- Python/ceval.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index 2ff2f9082e24c1..e3362006152add 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4336,9 +4336,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *next = (*Py_TYPE(iter)->tp_iternext)(iter); if (next != NULL) { PUSH(next); + JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); PREDICT(STORE_FAST); PREDICT(UNPACK_SEQUENCE); - JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); DISPATCH(); } if (_PyErr_Occurred(tstate)) { @@ -4359,7 +4359,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(FOR_ITER_ADAPTIVE) { - assert(cframe.use_tracing == 0); + // assert(cframe.use_tracing == 0); fails for some reason _PyForIterCache *cache = (_PyForIterCache *)next_instr; if (cache->counter == 0) { next_instr--; @@ -4374,7 +4374,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(FOR_ITER_LIST) { - assert(cframe.use_tracing == 0); + // assert(cframe.use_tracing == 0); fails for some reason _PyListIterObject *it = (_PyListIterObject *)TOP(); DEOPT_IF(Py_TYPE(it) != &PyListIter_Type, JUMP_BACKWARD); STAT_INC(JUMP_BACKWARD, hit); @@ -4395,7 +4395,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(FOR_ITER_RANGE) { - assert(cframe.use_tracing == 0); + // assert(cframe.use_tracing == 0); fails for some reason _PyRangeIterObject *r = (_PyRangeIterObject *)TOP(); DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER); STAT_INC(FOR_ITER, hit); From e429410ba16db8b385975f9616896c97f02bce89 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Tue, 19 Apr 2022 14:41:33 -0400 Subject: [PATCH 06/24] Make FOR_ITER_RANGE mutate the local --- Include/internal/pycore_range.h | 8 +++---- Objects/rangeobject.c | 25 ++++++++------------ Python/ceval.c | 41 ++++++++++++++++++++++++++------- Python/specialize.c | 6 +++-- 4 files changed, 50 insertions(+), 30 deletions(-) diff --git a/Include/internal/pycore_range.h b/Include/internal/pycore_range.h index 809e89a1e01b60..01e6ff9fbce7f5 100644 --- a/Include/internal/pycore_range.h +++ b/Include/internal/pycore_range.h @@ -10,10 +10,10 @@ extern "C" { typedef struct { PyObject_HEAD - long index; - long start; - long step; - long len; + sdigit index; + sdigit start; + sdigit step; + sdigit len; } _PyRangeIterObject; #ifdef __cplusplus diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index f0b06de1c7d2a0..83aa776978c5a6 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -770,7 +770,7 @@ rangeiter_next(_PyRangeIterObject *r) /* cast to unsigned to avoid possible signed overflow in intermediate calculations. */ return PyLong_FromLong((long)(r->start + - (unsigned long)(r->index++) * r->step)); + (digit)(r->index++) * r->step)); return NULL; } @@ -911,9 +911,9 @@ fast_range_iter(long start, long stop, long step, long len) _PyRangeIterObject *it = PyObject_New(_PyRangeIterObject, &PyRangeIter_Type); if (it == NULL) return NULL; - it->start = start; - it->step = step; - it->len = len; + it->start = Py_SAFE_DOWNCAST(start, long, sdigit); + it->step = Py_SAFE_DOWNCAST(step, long, sdigit); + it->len = Py_SAFE_DOWNCAST(len, long, sdigit); it->index = 0; return (PyObject *)it; } @@ -1097,20 +1097,13 @@ range_iter(PyObject *seq) goto long_range; } ulen = get_len_of_range(lstart, lstop, lstep); - if (ulen > (unsigned long)LONG_MAX) { + if (ulen > PyLong_MASK || + lstart > PyLong_MASK || lstart < -(long)PyLong_MASK || + lstop > PyLong_MASK || lstop < -(long)PyLong_MASK || + lstep > PyLong_MASK || lstep < -(long)PyLong_MASK) + { goto long_range; } - /* check for potential overflow of lstart + ulen * lstep */ - if (ulen) { - if (lstep > 0) { - if (lstop > LONG_MAX - (lstep - 1)) - goto long_range; - } - else { - if (lstop < LONG_MIN + (-1 - lstep)) - goto long_range; - } - } return fast_range_iter(lstart, lstop, lstep, (long)ulen); long_range: diff --git a/Python/ceval.c b/Python/ceval.c index e3362006152add..f6f9c093043155 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4399,17 +4399,42 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int _PyRangeIterObject *r = (_PyRangeIterObject *)TOP(); DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER); STAT_INC(FOR_ITER, hit); - if (r->index < r->len) { - PyObject *res = PyLong_FromLong( - (long)(r->start + (unsigned long)(r->index++) * r->step)); - if (res == NULL) { - goto error; + _Py_CODEUNIT next = next_instr[INLINE_CACHE_ENTRIES_FOR_ITER]; + assert(_PyOpcode_Deopt[_Py_OPCODE(next)] == STORE_FAST); + PyObject **local_ptr = &GETLOCAL(_Py_OPARG(next)); + PyObject *local = *local_ptr; + if (r->index >= r->len) { + goto iterator_exhausted_no_error; + } + JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + 1); + sdigit value = r->start + (digit)(r->index++) * r->step; + if (value < _PY_NSMALLPOSINTS && value >= -_PY_NSMALLNEGINTS) { + *local_ptr = Py_NewRef(&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+value]); + Py_XDECREF(local); + NOTRACE_DISPATCH(); + } + if (local && PyLong_CheckExact(local) && Py_REFCNT(local) == 1) { + if (value > 0) { + assert(value <= PyLong_MASK); + ((PyLongObject *)local)->ob_digit[0] = value; + Py_SET_SIZE(local, 1); + } + else { + assert(value >= -(sdigit)PyLong_MASK); + ((PyLongObject *)local)->ob_digit[0] = -(sdigit)value; + Py_SET_SIZE(local, -1); } - PUSH(res); - JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); NOTRACE_DISPATCH(); } - goto iterator_exhausted_no_error; + PyObject *res = PyLong_FromLong(value); + if (res == NULL) { + // undo the JUMPBY + next_instr -= INLINE_CACHE_ENTRIES_FOR_ITER + 1; + goto error; + } + *local_ptr = res; + Py_XDECREF(local); + NOTRACE_DISPATCH(); } TARGET(BEFORE_ASYNC_WITH) { diff --git a/Python/specialize.c b/Python/specialize.c index 1b12d6145a681e..58033624b87b1d 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -2064,16 +2064,18 @@ _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr) assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER); _PyForIterCache *cache = (_PyForIterCache *)(instr + 1); PyTypeObject *tp = Py_TYPE(iter); + _Py_CODEUNIT next = instr[1+INLINE_CACHE_ENTRIES_FOR_ITER]; + int next_op = _PyOpcode_Deopt[_Py_OPCODE(next)]; if (tp == &PyListIter_Type) { _Py_SET_OPCODE(*instr, FOR_ITER_LIST); goto success; } - else if (tp == &PyRangeIter_Type) { + else if (tp == &PyRangeIter_Type && next_op == STORE_FAST) { _Py_SET_OPCODE(*instr, FOR_ITER_RANGE); goto success; } else { - SPECIALIZATION_FAIL(JUMP_BACKWARD, + SPECIALIZATION_FAIL(FOR_ITER, _PySpecialization_ClassifyIterator(iter)); goto failure; } From 73fa01c9a12cfb8c03c3493bc0618a0e994dc067 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Tue, 19 Apr 2022 15:36:45 -0400 Subject: [PATCH 07/24] Fix overflow --- Objects/rangeobject.c | 9 ++++++++- Python/ceval.c | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 83aa776978c5a6..81d92c3bdba380 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -770,7 +770,7 @@ rangeiter_next(_PyRangeIterObject *r) /* cast to unsigned to avoid possible signed overflow in intermediate calculations. */ return PyLong_FromLong((long)(r->start + - (digit)(r->index++) * r->step)); + (unsigned long)(r->index++) * r->step)); return NULL; } @@ -1190,6 +1190,13 @@ range_reverse(PyObject *seq, PyObject *Py_UNUSED(ignored)) new_stop = lstart - lstep; new_start = (long)(new_stop + ulen * lstep); + if (ulen > PyLong_MASK || + new_start > PyLong_MASK || new_start < -(long)PyLong_MASK || + new_stop > PyLong_MASK || new_stop < -(long)PyLong_MASK || + lstep > PyLong_MASK || lstep < -(long)PyLong_MASK) + { + goto long_range; + } return fast_range_iter(new_start, new_stop, -lstep, (long)ulen); long_range: diff --git a/Python/ceval.c b/Python/ceval.c index 20907b5df2e8bc..66a8fc22c38436 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4426,7 +4426,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int else { assert(value >= -(sdigit)PyLong_MASK); ((PyLongObject *)local)->ob_digit[0] = -(sdigit)value; - Py_SET_SIZE(local, -1); + Py_SET_SIZE(local, (Py_ssize_t)-1); } NOTRACE_DISPATCH(); } From 4213582639f740623c57169c56c6e55cc3a45e01 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Tue, 19 Apr 2022 17:10:07 -0400 Subject: [PATCH 08/24] fix test --- Lib/test/test_sys.py | 2 +- Python/ceval.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index b70871ff551d9a..b7f21506f3b764 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1461,7 +1461,7 @@ def delx(self): del self.__x # PyCapsule # XXX # rangeiterator - check(iter(range(1)), size('4l')) + check(iter(range(1)), size('') + 4 * self.longdigit) # reverse check(reversed(''), size('nP')) # range diff --git a/Python/ceval.c b/Python/ceval.c index 66a8fc22c38436..4db487759dedef 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4419,7 +4419,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } if (local && PyLong_CheckExact(local) && Py_REFCNT(local) == 1) { if (value > 0) { - assert(value <= PyLong_MASK); + assert((digit)value <= PyLong_MASK); ((PyLongObject *)local)->ob_digit[0] = value; Py_SET_SIZE(local, 1); } From bf583581777dc4de630cde5543f287e48379ae76 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Tue, 19 Apr 2022 18:08:05 -0400 Subject: [PATCH 09/24] fix dis --- Lib/dis.py | 12 +- Lib/test/test_dis.py | 278 +++++++++++++++++++++---------------------- 2 files changed, 148 insertions(+), 142 deletions(-) diff --git a/Lib/dis.py b/Lib/dis.py index 205e9d8d193f32..9f69419b7f04b0 100644 --- a/Lib/dis.py +++ b/Lib/dis.py @@ -31,6 +31,7 @@ LOAD_GLOBAL = opmap['LOAD_GLOBAL'] BINARY_OP = opmap['BINARY_OP'] JUMP_BACKWARD = opmap['JUMP_BACKWARD'] +FOR_ITER = opmap['FOR_ITER'] CACHE = opmap["CACHE"] @@ -473,6 +474,8 @@ def _get_instructions_bytes(code, varname_from_oparg=None, elif deop in hasjrel: signed_arg = -arg if _is_backward_jump(deop) else arg argval = offset + 2 + signed_arg*2 + if deop == FOR_ITER: + argval += 2 argrepr = "to " + repr(argval) elif deop in haslocal or deop in hasfree: argval, argrepr = _get_name_info(arg, varname_from_oparg) @@ -596,11 +599,14 @@ def findlabels(code): labels = [] for offset, op, arg in _unpack_opargs(code): if arg is not None: - if op in hasjrel: - if _is_backward_jump(op): + deop = _deoptop(op) + if deop in hasjrel: + if _is_backward_jump(deop): arg = -arg label = offset + 2 + arg*2 - elif op in hasjabs: + if deop == FOR_ITER: + label += 2 + elif deop in hasjabs: label = arg*2 else: continue diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index f560a5556c8b0e..017734318c51fd 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -146,10 +146,10 @@ def bug708901(): %3d PRECALL 2 CALL 2 GET_ITER - >> FOR_ITER 2 (to 40) + >> FOR_ITER 2 (to 42) STORE_FAST 0 (res) -%3d JUMP_BACKWARD 3 (to 34) +%3d JUMP_BACKWARD 4 (to 34) %3d >> LOAD_CONST 0 (None) RETURN_VALUE @@ -569,13 +569,13 @@ def foo(x): %3d RESUME 0 BUILD_LIST 0 LOAD_FAST 0 (.0) - >> FOR_ITER 7 (to 24) + >> FOR_ITER 7 (to 26) STORE_FAST 1 (z) LOAD_DEREF 2 (x) LOAD_FAST 1 (z) BINARY_OP 0 (+) LIST_APPEND 2 - JUMP_BACKWARD 8 (to 8) + JUMP_BACKWARD 9 (to 8) >> RETURN_VALUE """ % (dis_nested_1, __file__, @@ -616,18 +616,18 @@ def loop_test(): 8 LOAD_CONST 2 (3) 10 BINARY_OP_ADAPTIVE 5 (*) 14 GET_ITER - 16 FOR_ITER 17 (to 52) - 18 STORE_FAST 0 (i) - -%3d 20 LOAD_GLOBAL_MODULE 1 (NULL + load_test) - 32 LOAD_FAST 0 (i) - 34 PRECALL_PYFUNC 1 - 38 CALL_PY_WITH_DEFAULTS 1 - 48 POP_TOP - 50 JUMP_BACKWARD_QUICK 18 (to 16) - -%3d >> 52 LOAD_CONST 0 (None) - 54 RETURN_VALUE + >> 16 FOR_ITER_LIST 17 (to 54) + 20 STORE_FAST 0 (i) + +%3d 22 LOAD_GLOBAL_MODULE 1 (NULL + load_test) + 34 LOAD_FAST 0 (i) + 36 PRECALL_PYFUNC 1 + 40 CALL_PY_WITH_DEFAULTS 1 + 50 POP_TOP + 52 JUMP_BACKWARD_QUICK 19 (to 16) + +%3d >> 54 LOAD_CONST 0 (None) + 56 RETURN_VALUE """ % (loop_test.__code__.co_firstlineno, loop_test.__code__.co_firstlineno + 1, loop_test.__code__.co_firstlineno + 2, @@ -1352,131 +1352,131 @@ def _prepare_test_cases(): Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=20, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=30, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='FOR_ITER', opcode=93, arg=32, argval=98, argrepr='to 98', offset=32, starts_line=None, is_jump_target=True, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=34, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=36, starts_line=4, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=48, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=50, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=54, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=64, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=66, starts_line=5, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=68, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=70, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=80, argrepr='to 80', offset=76, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=24, argval=32, argrepr='to 32', offset=78, starts_line=6, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=80, starts_line=7, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=82, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=84, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=2, argval=96, argrepr='to 96', offset=90, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=92, starts_line=8, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=16, argval=128, argrepr='to 128', offset=94, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=33, argval=32, argrepr='to 32', offset=96, starts_line=7, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=98, starts_line=10, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=110, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=112, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=116, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=128, starts_line=11, is_jump_target=True, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=36, argval=204, argrepr='to 204', offset=130, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=132, starts_line=12, is_jump_target=True, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=144, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=146, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=150, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=162, starts_line=13, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=164, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=166, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=170, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=172, starts_line=14, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=174, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=176, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=186, argrepr='to 186', offset=182, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=29, argval=128, argrepr='to 128', offset=184, starts_line=15, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=186, starts_line=16, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=188, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=190, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=200, argrepr='to 200', offset=196, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=17, argval=234, argrepr='to 234', offset=198, starts_line=17, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=200, starts_line=11, is_jump_target=True, positions=None), - Instruction(opname='POP_JUMP_BACKWARD_IF_TRUE', opcode=176, arg=36, argval=132, argrepr='to 132', offset=202, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=204, starts_line=19, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=216, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=222, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=232, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=234, starts_line=20, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=236, starts_line=21, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=238, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=240, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=244, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=246, starts_line=25, is_jump_target=False, positions=None), - Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=248, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=250, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=252, starts_line=26, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=264, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=266, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=270, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=280, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=282, starts_line=25, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=284, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='FOR_ITER', opcode=93, arg=32, argval=100, argrepr='to 100', offset=32, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=36, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=38, starts_line=4, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=50, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=52, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=56, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=66, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=68, starts_line=5, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=70, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=72, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=82, argrepr='to 82', offset=78, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=140, arg=25, argval=32, argrepr='to 32', offset=80, starts_line=6, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=82, starts_line=7, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=84, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=86, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=2, argval=98, argrepr='to 98', offset=92, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=94, starts_line=8, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=16, argval=130, argrepr='to 130', offset=96, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=140, arg=34, argval=32, argrepr='to 32', offset=98, starts_line=7, is_jump_target=True, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=100, starts_line=10, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=112, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=114, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=118, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=128, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=130, starts_line=11, is_jump_target=True, positions=None), + Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=36, argval=206, argrepr='to 206', offset=132, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=134, starts_line=12, is_jump_target=True, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=146, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=148, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=152, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=164, starts_line=13, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=166, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=168, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=172, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=174, starts_line=14, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=176, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=178, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=188, argrepr='to 188', offset=184, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=140, arg=29, argval=130, argrepr='to 130', offset=186, starts_line=15, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=188, starts_line=16, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=190, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=192, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=202, argrepr='to 202', offset=198, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=17, argval=236, argrepr='to 236', offset=200, starts_line=17, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=202, starts_line=11, is_jump_target=True, positions=None), + Instruction(opname='POP_JUMP_BACKWARD_IF_TRUE', opcode=176, arg=36, argval=134, argrepr='to 134', offset=204, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=206, starts_line=19, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=218, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=220, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=234, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=236, starts_line=20, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=238, starts_line=21, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=240, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=242, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=246, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=248, starts_line=25, is_jump_target=False, positions=None), + Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=250, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=252, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=254, starts_line=26, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=266, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=268, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=272, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=282, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=284, starts_line=25, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=286, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=2, argval=2, argrepr='', offset=288, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=292, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=302, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=328, argrepr='to 328', offset=304, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=306, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=308, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_TRUE', opcode=115, arg=4, argval=320, argrepr='to 320', offset=310, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=312, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=314, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=316, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=318, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=320, starts_line=None, is_jump_target=True, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=322, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=324, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=288, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PRECALL', opcode=166, arg=2, argval=2, argrepr='', offset=290, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=294, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=304, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=330, argrepr='to 330', offset=306, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=308, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=310, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_FORWARD_IF_TRUE', opcode=115, arg=4, argval=322, argrepr='to 322', offset=312, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=314, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=316, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=318, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=320, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=322, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=324, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=326, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=31, argval=392, argrepr='to 392', offset=328, starts_line=None, is_jump_target=True, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=330, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=332, starts_line=22, is_jump_target=False, positions=None), - Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=344, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=18, argval=384, argrepr='to 384', offset=346, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=348, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=350, starts_line=23, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=362, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=364, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=368, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=378, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=380, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=21, argval=426, argrepr='to 426', offset=382, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=384, starts_line=22, is_jump_target=True, positions=None), - Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=386, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=388, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=390, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=392, starts_line=28, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=404, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=406, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=410, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=420, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=422, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=424, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=426, starts_line=23, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=428, starts_line=28, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=440, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=442, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=446, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=456, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=458, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=460, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=462, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=464, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=476, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=478, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=482, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=492, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=494, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=496, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=498, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=500, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=328, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=31, argval=394, argrepr='to 394', offset=330, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=332, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=334, starts_line=22, is_jump_target=False, positions=None), + Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=346, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=18, argval=386, argrepr='to 386', offset=348, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=350, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=352, starts_line=23, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=364, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=366, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=370, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=380, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=382, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=21, argval=428, argrepr='to 428', offset=384, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=386, starts_line=22, is_jump_target=True, positions=None), + Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=388, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=390, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=392, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=394, starts_line=28, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=406, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=408, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=412, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=422, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=424, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=426, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=428, starts_line=23, is_jump_target=True, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=430, starts_line=28, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=442, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=444, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=448, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=458, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=460, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=462, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=464, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=466, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=478, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=480, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=484, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=494, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=496, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=498, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=500, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=502, starts_line=None, is_jump_target=False, positions=None), ] # One last piece of inspect fodder to check the default line number handling From bd7575e495860e420bef7e9692f1eda7ea39ee66 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Tue, 19 Apr 2022 19:33:16 -0400 Subject: [PATCH 10/24] Add more tests, add more casts --- Lib/test/test_range.py | 9 +++++---- Objects/rangeobject.c | 16 ++++++++-------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py index 851ad5b7c2f485..93bff414049dcb 100644 --- a/Lib/test/test_range.py +++ b/Lib/test/test_range.py @@ -507,7 +507,7 @@ def test_range_iterators(self): # exercise 'fast' iterators, that use a rangeiterobject internally. # see issue 7298 limits = [base + jiggle - for M in (2**32, 2**64) + for M in (2**15, 2**30, 2**32, 2**64) for base in (-M, -M//2, 0, M//2, M) for jiggle in (-2, -1, 0, 1, 2)] test_ranges = [(start, end, step) @@ -519,13 +519,14 @@ def test_range_iterators(self): iter1 = range(start, end, step) iter2 = pyrange(start, end, step) test_id = "range({}, {}, {})".format(start, end, step) - # check first 100 entries - self.assert_iterators_equal(iter1, iter2, test_id, limit=100) + # check first 10 entries + self.assert_iterators_equal(iter1, iter2, test_id, limit=10) iter1 = reversed(range(start, end, step)) iter2 = pyrange_reversed(start, end, step) test_id = "reversed(range({}, {}, {}))".format(start, end, step) - self.assert_iterators_equal(iter1, iter2, test_id, limit=100) + self.assert_iterators_equal(iter1, iter2, test_id, limit=10) + def test_range_iterators_invocation(self): # verify range iterators instances cannot be created by diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 81d92c3bdba380..1c2f692cc25562 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -1097,10 +1097,10 @@ range_iter(PyObject *seq) goto long_range; } ulen = get_len_of_range(lstart, lstop, lstep); - if (ulen > PyLong_MASK || - lstart > PyLong_MASK || lstart < -(long)PyLong_MASK || - lstop > PyLong_MASK || lstop < -(long)PyLong_MASK || - lstep > PyLong_MASK || lstep < -(long)PyLong_MASK) + if (ulen > (long)PyLong_MASK || + lstart > (long)PyLong_MASK || lstart < -(long)PyLong_MASK || + lstop > (long)PyLong_MASK || lstop < -(long)PyLong_MASK || + lstep > (long)PyLong_MASK || lstep < -(long)PyLong_MASK) { goto long_range; } @@ -1190,10 +1190,10 @@ range_reverse(PyObject *seq, PyObject *Py_UNUSED(ignored)) new_stop = lstart - lstep; new_start = (long)(new_stop + ulen * lstep); - if (ulen > PyLong_MASK || - new_start > PyLong_MASK || new_start < -(long)PyLong_MASK || - new_stop > PyLong_MASK || new_stop < -(long)PyLong_MASK || - lstep > PyLong_MASK || lstep < -(long)PyLong_MASK) + if (ulen > (long)PyLong_MASK || + new_start > (long)PyLong_MASK || new_start < -(long)PyLong_MASK || + new_stop > (long)PyLong_MASK || new_stop < -(long)PyLong_MASK || + lstep > (long)PyLong_MASK || lstep < -(long)PyLong_MASK) { goto long_range; } From 824e966394bada84816b6aef1d79831319c6138e Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Sat, 23 Apr 2022 22:17:12 -0400 Subject: [PATCH 11/24] Fix stats, take out some PREDICT --- Python/ceval.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index d8365fe06ca4b4..43acf7856401ae 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4349,7 +4349,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int SET_TOP(iter); if (iter == NULL) goto error; - PREDICT(FOR_ITER); DISPATCH(); } @@ -4390,8 +4389,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (next != NULL) { PUSH(next); JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); - PREDICT(STORE_FAST); - PREDICT(UNPACK_SEQUENCE); DISPATCH(); } if (_PyErr_Occurred(tstate)) { @@ -4429,8 +4426,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(FOR_ITER_LIST) { // assert(cframe.use_tracing == 0); fails for some reason _PyListIterObject *it = (_PyListIterObject *)TOP(); - DEOPT_IF(Py_TYPE(it) != &PyListIter_Type, JUMP_BACKWARD); - STAT_INC(JUMP_BACKWARD, hit); + DEOPT_IF(Py_TYPE(it) != &PyListIter_Type, FOR_ITER); + STAT_INC(FOR_ITER, hit); PyListObject *seq = it->it_seq; if (seq == NULL) { goto iterator_exhausted_no_error; From 6b16772671849ef4e90b4091884d13b1219486eb Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sun, 24 Apr 2022 02:22:12 +0000 Subject: [PATCH 12/24] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2022-04-24-02-22-10.gh-issue-91432.YPJAK6.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-04-24-02-22-10.gh-issue-91432.YPJAK6.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-04-24-02-22-10.gh-issue-91432.YPJAK6.rst b/Misc/NEWS.d/next/Core and Builtins/2022-04-24-02-22-10.gh-issue-91432.YPJAK6.rst new file mode 100644 index 00000000000000..081dc0f5c334c5 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-04-24-02-22-10.gh-issue-91432.YPJAK6.rst @@ -0,0 +1 @@ +Specialized the :opcode:`FOR_ITER` opcode using the PEP 659 machinery From 6696384d9e57ade86f3d449cfb11ba622aae2b0f Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Thu, 28 Apr 2022 00:50:01 -0400 Subject: [PATCH 13/24] remove PREDEICTED(STORE_FAST) --- Python/ceval.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Python/ceval.c b/Python/ceval.c index 214b3282d5cd96..6fb7b5143de01c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1881,7 +1881,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(STORE_FAST) { - PREDICTED(STORE_FAST); PyObject *value = POP(); SETLOCAL(oparg, value); DISPATCH(); From d2970911cc17c938670900f5d6add18039b939b8 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Thu, 28 Apr 2022 00:52:17 -0400 Subject: [PATCH 14/24] assert no tracing --- Python/ceval.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index 6fb7b5143de01c..21655174a944ca 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4409,7 +4409,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(FOR_ITER_ADAPTIVE) { - // assert(cframe.use_tracing == 0); fails for some reason + assert(cframe.use_tracing == 0); _PyForIterCache *cache = (_PyForIterCache *)next_instr; if (cache->counter == 0) { next_instr--; @@ -4424,7 +4424,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(FOR_ITER_LIST) { - // assert(cframe.use_tracing == 0); fails for some reason + assert(cframe.use_tracing == 0); _PyListIterObject *it = (_PyListIterObject *)TOP(); DEOPT_IF(Py_TYPE(it) != &PyListIter_Type, FOR_ITER); STAT_INC(FOR_ITER, hit); @@ -4445,7 +4445,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(FOR_ITER_RANGE) { - // assert(cframe.use_tracing == 0); fails for some reason + assert(cframe.use_tracing == 0); _PyRangeIterObject *r = (_PyRangeIterObject *)TOP(); DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER); STAT_INC(FOR_ITER, hit); From f360d65f344e7b1e1b7c4c85369ff70a36800e7a Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Thu, 28 Apr 2022 01:30:22 -0400 Subject: [PATCH 15/24] remove unnecessary cast --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/ceval.c b/Python/ceval.c index 21655174a944ca..40efabf031a122 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4471,7 +4471,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } else { assert(value >= -(sdigit)PyLong_MASK); - ((PyLongObject *)local)->ob_digit[0] = -(sdigit)value; + ((PyLongObject *)local)->ob_digit[0] = -value; Py_SET_SIZE(local, (Py_ssize_t)-1); } NOTRACE_DISPATCH(); From c2eab689b1d0773b144cd22570477cd03e9080ba Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Tue, 3 May 2022 11:35:19 -0400 Subject: [PATCH 16/24] regen --- Include/internal/pycore_opcode.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Include/internal/pycore_opcode.h b/Include/internal/pycore_opcode.h index f7b3c89c08f9bc..7fa458835bdd83 100644 --- a/Include/internal/pycore_opcode.h +++ b/Include/internal/pycore_opcode.h @@ -298,6 +298,9 @@ const uint8_t _PyOpcode_Original[256] = { [EXTENDED_ARG_QUICK] = EXTENDED_ARG_QUICK, [FORMAT_VALUE] = FORMAT_VALUE, [FOR_ITER] = FOR_ITER, + [FOR_ITER_ADAPTIVE] = FOR_ITER, + [FOR_ITER_LIST] = FOR_ITER, + [FOR_ITER_RANGE] = FOR_ITER, [GET_AITER] = GET_AITER, [GET_ANEXT] = GET_ANEXT, [GET_AWAITABLE] = GET_AWAITABLE, From 91d280c05caf9dbe3114745ef9314afed6643aa4 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Mon, 9 May 2022 21:52:20 -0400 Subject: [PATCH 17/24] Fix test_dis --- Lib/test/test_dis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 46f8734a30d295..53130265de37cf 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -1040,7 +1040,7 @@ def test_show_caches(self): for cache in caches: self.assertRegex(cache, pattern) self.assertEqual(caches.count(""), 8) - self.assertEqual(len(caches), 25) + self.assertEqual(len(caches), 26) class DisWithFileTests(DisTests): From 6cdf0e418d7b95eec7a16e9b7c086fc0ce531027 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Thu, 9 Jun 2022 17:38:01 -0400 Subject: [PATCH 18/24] Add comment about re-using the old PyLongObject --- Python/ceval.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Python/ceval.c b/Python/ceval.c index 8753837953e8b7..4693941d3229a3 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4415,6 +4415,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int NOTRACE_DISPATCH(); } if (local && PyLong_CheckExact(local) && Py_REFCNT(local) == 1) { + /* A value from a range iterator is to be stored in a + local variable, and that local variable's existing + value is a PyLongObject not referenced elsewhere. + To avoid an allocation, re-use the existing + PyLongObject for the new value. */ if (value > 0) { assert((digit)value <= PyLong_MASK); ((PyLongObject *)local)->ob_digit[0] = value; From ed29777640589fbb231c527fb52c76f6682c9e97 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Mon, 13 Jun 2022 20:32:40 -0400 Subject: [PATCH 19/24] use the new exponential backoff --- Python/ceval.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index 4693941d3229a3..9c45d3eea09791 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4362,14 +4362,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(FOR_ITER_ADAPTIVE) { assert(cframe.use_tracing == 0); _PyForIterCache *cache = (_PyForIterCache *)next_instr; - if (cache->counter == 0) { + if (ADAPTIVE_COUNTER_IS_ZERO(cache)) { next_instr--; _Py_Specialize_ForIter(TOP(), next_instr); NOTRACE_DISPATCH_SAME_OPARG(); } else { STAT_INC(FOR_ITER, deferred); - cache->counter--; + DECREMENT_ADAPTIVE_COUNTER(cache); JUMP_TO_INSTRUCTION(FOR_ITER); } } From 36d0999780848f5d115287d307a913b9fb4c2a62 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Sat, 18 Jun 2022 20:10:31 -0400 Subject: [PATCH 20/24] revert using sdigits, add _PyLong_AssignValue --- Include/internal/pycore_long.h | 2 ++ Include/internal/pycore_range.h | 8 +++---- Objects/longobject.c | 29 ++++++++++++++++++++++++++ Objects/rangeobject.c | 30 +++++++++++++------------- Python/ceval.c | 37 ++++----------------------------- 5 files changed, 54 insertions(+), 52 deletions(-) diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index a33762402491b7..9f8d9bd758786a 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -47,6 +47,8 @@ PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right); PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right); PyObject *_PyLong_Subtract(PyLongObject *left, PyLongObject *right); +int _PyLong_AssignValue(PyObject **target, long value); + /* Used by Python/mystrtoul.c, _PyBytes_FromHex(), _PyBytes_DecodeEscape(), etc. */ PyAPI_DATA(unsigned char) _PyLong_DigitValue[256]; diff --git a/Include/internal/pycore_range.h b/Include/internal/pycore_range.h index 01e6ff9fbce7f5..809e89a1e01b60 100644 --- a/Include/internal/pycore_range.h +++ b/Include/internal/pycore_range.h @@ -10,10 +10,10 @@ extern "C" { typedef struct { PyObject_HEAD - sdigit index; - sdigit start; - sdigit step; - sdigit len; + long index; + long start; + long step; + long len; } _PyRangeIterObject; #ifdef __cplusplus diff --git a/Objects/longobject.c b/Objects/longobject.c index 14d5954f84849e..bfbe138403f03d 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -262,6 +262,35 @@ _PyLong_FromSTwoDigits(stwodigits x) return _PyLong_FromLarge(x); } +int +_PyLong_AssignValue(PyObject **target, long value) +{ + PyObject *old = *target; + if (IS_SMALL_INT(value)) { + *target = get_small_int(Py_SAFE_DOWNCAST(value, long, sdigit)); + Py_XDECREF(old); + return 0; + } + else if (old != NULL && PyLong_CheckExact(old) && + Py_REFCNT(old) == 1 && Py_SIZE(old) == 1 && + (unsigned long)value <= PyLong_MASK) + { + // Mutate in place if there are no other references to the old object. + // This avoids an allocation in a common case. + ((PyLongObject *)old)->ob_digit[0] + = Py_SAFE_DOWNCAST(value, long, digit); + return 0; + } + else { + *target = PyLong_FromLong(value); + Py_XDECREF(old); + if (*target == NULL) { + return -1; + } + return 0; + } +} + /* If a freshly-allocated int is already shared, it must be a small integer, so negating it must go to PyLong_FromLong */ Py_LOCAL_INLINE(void) diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 1c2f692cc25562..f0b06de1c7d2a0 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -911,9 +911,9 @@ fast_range_iter(long start, long stop, long step, long len) _PyRangeIterObject *it = PyObject_New(_PyRangeIterObject, &PyRangeIter_Type); if (it == NULL) return NULL; - it->start = Py_SAFE_DOWNCAST(start, long, sdigit); - it->step = Py_SAFE_DOWNCAST(step, long, sdigit); - it->len = Py_SAFE_DOWNCAST(len, long, sdigit); + it->start = start; + it->step = step; + it->len = len; it->index = 0; return (PyObject *)it; } @@ -1097,13 +1097,20 @@ range_iter(PyObject *seq) goto long_range; } ulen = get_len_of_range(lstart, lstop, lstep); - if (ulen > (long)PyLong_MASK || - lstart > (long)PyLong_MASK || lstart < -(long)PyLong_MASK || - lstop > (long)PyLong_MASK || lstop < -(long)PyLong_MASK || - lstep > (long)PyLong_MASK || lstep < -(long)PyLong_MASK) - { + if (ulen > (unsigned long)LONG_MAX) { goto long_range; } + /* check for potential overflow of lstart + ulen * lstep */ + if (ulen) { + if (lstep > 0) { + if (lstop > LONG_MAX - (lstep - 1)) + goto long_range; + } + else { + if (lstop < LONG_MIN + (-1 - lstep)) + goto long_range; + } + } return fast_range_iter(lstart, lstop, lstep, (long)ulen); long_range: @@ -1190,13 +1197,6 @@ range_reverse(PyObject *seq, PyObject *Py_UNUSED(ignored)) new_stop = lstart - lstep; new_start = (long)(new_stop + ulen * lstep); - if (ulen > (long)PyLong_MASK || - new_start > (long)PyLong_MASK || new_start < -(long)PyLong_MASK || - new_stop > (long)PyLong_MASK || new_stop < -(long)PyLong_MASK || - lstep > (long)PyLong_MASK || lstep < -(long)PyLong_MASK) - { - goto long_range; - } return fast_range_iter(new_start, new_stop, -lstep, (long)ulen); long_range: diff --git a/Python/ceval.c b/Python/ceval.c index 9737bae6438518..24202e8f7290d7 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4502,44 +4502,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int STAT_INC(FOR_ITER, hit); _Py_CODEUNIT next = next_instr[INLINE_CACHE_ENTRIES_FOR_ITER]; assert(_PyOpcode_Deopt[_Py_OPCODE(next)] == STORE_FAST); - PyObject **local_ptr = &GETLOCAL(_Py_OPARG(next)); - PyObject *local = *local_ptr; if (r->index >= r->len) { goto iterator_exhausted_no_error; } - JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + 1); - sdigit value = r->start + (digit)(r->index++) * r->step; - if (value < _PY_NSMALLPOSINTS && value >= -_PY_NSMALLNEGINTS) { - *local_ptr = Py_NewRef(&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+value]); - Py_XDECREF(local); - NOTRACE_DISPATCH(); - } - if (local && PyLong_CheckExact(local) && Py_REFCNT(local) == 1) { - /* A value from a range iterator is to be stored in a - local variable, and that local variable's existing - value is a PyLongObject not referenced elsewhere. - To avoid an allocation, re-use the existing - PyLongObject for the new value. */ - if (value > 0) { - assert((digit)value <= PyLong_MASK); - ((PyLongObject *)local)->ob_digit[0] = value; - Py_SET_SIZE(local, 1); - } - else { - assert(value >= -(sdigit)PyLong_MASK); - ((PyLongObject *)local)->ob_digit[0] = -value; - Py_SET_SIZE(local, (Py_ssize_t)-1); - } - NOTRACE_DISPATCH(); - } - PyObject *res = PyLong_FromLong(value); - if (res == NULL) { - // undo the JUMPBY - next_instr -= INLINE_CACHE_ENTRIES_FOR_ITER + 1; + long value = (long)(r->start + + (unsigned long)(r->index++) * r->step); + if (_PyLong_AssignValue(&GETLOCAL(_Py_OPARG(next)), value) < 0) { goto error; } - *local_ptr = res; - Py_XDECREF(local); + JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + 1); NOTRACE_DISPATCH(); } From ad2e9696dba3054a92040e687fa5125cb7e74684 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Sat, 18 Jun 2022 20:38:33 -0400 Subject: [PATCH 21/24] revert test_sys sizeof check --- Lib/test/test_sys.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 1617c26b662794..1dc10d8b0a39ac 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1470,7 +1470,7 @@ def delx(self): del self.__x # PyCapsule # XXX # rangeiterator - check(iter(range(1)), size('') + 4 * self.longdigit) + check(iter(range(1)), size('4l')) # reverse check(reversed(''), size('nP')) # range From d55868f9a35497b51b21eff34f7386181ae9e645 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Sun, 19 Jun 2022 05:59:42 -0400 Subject: [PATCH 22/24] revert test_range changes --- Lib/test/test_range.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py index 93bff414049dcb..851ad5b7c2f485 100644 --- a/Lib/test/test_range.py +++ b/Lib/test/test_range.py @@ -507,7 +507,7 @@ def test_range_iterators(self): # exercise 'fast' iterators, that use a rangeiterobject internally. # see issue 7298 limits = [base + jiggle - for M in (2**15, 2**30, 2**32, 2**64) + for M in (2**32, 2**64) for base in (-M, -M//2, 0, M//2, M) for jiggle in (-2, -1, 0, 1, 2)] test_ranges = [(start, end, step) @@ -519,14 +519,13 @@ def test_range_iterators(self): iter1 = range(start, end, step) iter2 = pyrange(start, end, step) test_id = "range({}, {}, {})".format(start, end, step) - # check first 10 entries - self.assert_iterators_equal(iter1, iter2, test_id, limit=10) + # check first 100 entries + self.assert_iterators_equal(iter1, iter2, test_id, limit=100) iter1 = reversed(range(start, end, step)) iter2 = pyrange_reversed(start, end, step) test_id = "reversed(range({}, {}, {}))".format(start, end, step) - self.assert_iterators_equal(iter1, iter2, test_id, limit=10) - + self.assert_iterators_equal(iter1, iter2, test_id, limit=100) def test_range_iterators_invocation(self): # verify range iterators instances cannot be created by From 2d6ee26f9528c459e1a228a337c7be45f44f8775 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Mon, 20 Jun 2022 09:51:39 -0400 Subject: [PATCH 23/24] add comment and use Py_ssize_t --- Include/internal/pycore_long.h | 2 +- Objects/longobject.c | 10 +++++----- Python/ceval.c | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index 9f8d9bd758786a..67dd5c3b13ec59 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -47,7 +47,7 @@ PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right); PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right); PyObject *_PyLong_Subtract(PyLongObject *left, PyLongObject *right); -int _PyLong_AssignValue(PyObject **target, long value); +int _PyLong_AssignValue(PyObject **target, Py_ssize_t value); /* Used by Python/mystrtoul.c, _PyBytes_FromHex(), _PyBytes_DecodeEscape(), etc. */ diff --git a/Objects/longobject.c b/Objects/longobject.c index bfbe138403f03d..c8a6c1cbd56a35 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -263,26 +263,26 @@ _PyLong_FromSTwoDigits(stwodigits x) } int -_PyLong_AssignValue(PyObject **target, long value) +_PyLong_AssignValue(PyObject **target, Py_ssize_t value) { PyObject *old = *target; if (IS_SMALL_INT(value)) { - *target = get_small_int(Py_SAFE_DOWNCAST(value, long, sdigit)); + *target = get_small_int(Py_SAFE_DOWNCAST(value, Py_ssize_t, sdigit)); Py_XDECREF(old); return 0; } else if (old != NULL && PyLong_CheckExact(old) && Py_REFCNT(old) == 1 && Py_SIZE(old) == 1 && - (unsigned long)value <= PyLong_MASK) + (size_t)value <= PyLong_MASK) { // Mutate in place if there are no other references to the old object. // This avoids an allocation in a common case. ((PyLongObject *)old)->ob_digit[0] - = Py_SAFE_DOWNCAST(value, long, digit); + = Py_SAFE_DOWNCAST(value, Py_ssize_t, digit); return 0; } else { - *target = PyLong_FromLong(value); + *target = PyLong_FromSsize_t(value); Py_XDECREF(old); if (*target == NULL) { return -1; diff --git a/Python/ceval.c b/Python/ceval.c index 24202e8f7290d7..6a16556bca6759 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4510,6 +4510,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_PyLong_AssignValue(&GETLOCAL(_Py_OPARG(next)), value) < 0) { goto error; } + // The STORE_FAST is already done. JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + 1); NOTRACE_DISPATCH(); } From db21da1efc431ef69bfc866bb666968274ba9033 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Mon, 20 Jun 2022 10:25:20 -0400 Subject: [PATCH 24/24] Add comment: only positive --- Objects/longobject.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index c8a6c1cbd56a35..4a1e5caf5a2843 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -275,10 +275,13 @@ _PyLong_AssignValue(PyObject **target, Py_ssize_t value) Py_REFCNT(old) == 1 && Py_SIZE(old) == 1 && (size_t)value <= PyLong_MASK) { - // Mutate in place if there are no other references to the old object. - // This avoids an allocation in a common case. - ((PyLongObject *)old)->ob_digit[0] - = Py_SAFE_DOWNCAST(value, Py_ssize_t, digit); + // Mutate in place if there are no other references the old + // object. This avoids an allocation in a common case. + // Since the primary use-case is iterating over ranges, which + // are typically positive, only do this optimization + // for positive integers (for now). + ((PyLongObject *)old)->ob_digit[0] = + Py_SAFE_DOWNCAST(value, Py_ssize_t, digit); return 0; } else {