From 5f05a186eef8517a40d003e4f01d3c8c2f07d5a5 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Sat, 16 Apr 2022 22:52:18 -0400 Subject: [PATCH 01/11] Don't ignore extended args of adaptive opcodes --- Lib/test/test_unpack.py | 37 +++++++++++++++++++++++++++++++++++++ Python/ceval.c | 31 ++++++++++++++++++++----------- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_unpack.py b/Lib/test/test_unpack.py index 472c8343eb2433..528df533fe354f 100644 --- a/Lib/test/test_unpack.py +++ b/Lib/test/test_unpack.py @@ -150,6 +150,43 @@ def load_tests(loader, tests, pattern): tests.addTest(doctest.DocTestSuite()) return tests +def unpack_400(x): + # UNPACK_SEQUENCE 400 + # is actually + # EXTENDED_ARG 1 + # UNPACK_SEQUENCE 144 + ( + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, + ) = x + return y + +class TestCornerCases(unittest.TestCase): + def test_extended_oparg_not_ignored(self): + for _ in range(30): + y = unpack_400(range(400)) + self.assertEqual(y, 399) if __name__ == "__main__": unittest.main() diff --git a/Python/ceval.c b/Python/ceval.c index d358a3134bc63a..05dd27f2689889 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1351,6 +1351,15 @@ eval_frame_handle_pending(PyThreadState *tstate) DISPATCH_GOTO(); \ } +#define DISPATCH_SAME_OPARG() \ + { \ + opcode = _Py_OPCODE(*next_instr); \ + PRE_DISPATCH_GOTO(); \ + assert(cframe.use_tracing == 0 || cframe.use_tracing == 255); \ + opcode |= cframe.use_tracing OR_DTRACE_LINE; \ + DISPATCH_GOTO(); \ + } + #define CHECK_EVAL_BREAKER() \ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); \ if (_Py_atomic_load_relaxed(eval_breaker)) { \ @@ -2158,7 +2167,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_BinarySubscr(container, sub, next_instr) < 0) { goto error; } - DISPATCH(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(BINARY_SUBSCR, deferred); @@ -2323,7 +2332,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_StoreSubscr(container, sub, next_instr) < 0) { goto error; } - DISPATCH(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(STORE_SUBSCR, deferred); @@ -2813,7 +2822,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *seq = TOP(); next_instr--; _Py_Specialize_UnpackSequence(seq, next_instr, oparg); - DISPATCH(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(UNPACK_SEQUENCE, deferred); @@ -3056,7 +3065,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name) < 0) { goto error; } - DISPATCH(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(LOAD_GLOBAL, deferred); @@ -3481,7 +3490,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_LoadAttr(owner, next_instr, name) < 0) { goto error; } - DISPATCH(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(LOAD_ATTR, deferred); @@ -3590,7 +3599,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_StoreAttr(owner, next_instr, name) < 0) { goto error; } - DISPATCH(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(STORE_ATTR, deferred); @@ -3718,7 +3727,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *left = SECOND(); next_instr--; _Py_Specialize_CompareOp(left, right, next_instr, oparg); - DISPATCH(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(COMPARE_OP, deferred); @@ -4523,7 +4532,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_LoadMethod(owner, next_instr, name) < 0) { goto error; } - DISPATCH(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(LOAD_METHOD, deferred); @@ -4797,7 +4806,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (err < 0) { goto error; } - DISPATCH(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(PRECALL, deferred); @@ -4818,7 +4827,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (err < 0) { goto error; } - DISPATCH(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(CALL, deferred); @@ -5545,7 +5554,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *rhs = TOP(); next_instr--; _Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg, &GETLOCAL(0)); - DISPATCH(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(BINARY_OP, deferred); From 78481c07394c071d540fd2b9dfc23462d947ed6e Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sun, 17 Apr 2022 02:55:39 +0000 Subject: [PATCH 02/11] =?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-17-02-55-38.gh-issue-91625.80CrC7.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-04-17-02-55-38.gh-issue-91625.80CrC7.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-04-17-02-55-38.gh-issue-91625.80CrC7.rst b/Misc/NEWS.d/next/Core and Builtins/2022-04-17-02-55-38.gh-issue-91625.80CrC7.rst new file mode 100644 index 00000000000000..b15043f186d348 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-04-17-02-55-38.gh-issue-91625.80CrC7.rst @@ -0,0 +1 @@ +Fixed a bug in which adaptive opcodes ignored any preceding ``EXTENDED_ARG``s on specialization failure. From f4a7b8733351706e68021ac2f6aad5b368f62379 Mon Sep 17 00:00:00 2001 From: Dennis Sweeney <36520290+sweeneyde@users.noreply.github.com> Date: Sat, 16 Apr 2022 23:00:08 -0400 Subject: [PATCH 03/11] ReStructuredText issue --- .../2022-04-17-02-55-38.gh-issue-91625.80CrC7.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-04-17-02-55-38.gh-issue-91625.80CrC7.rst b/Misc/NEWS.d/next/Core and Builtins/2022-04-17-02-55-38.gh-issue-91625.80CrC7.rst index b15043f186d348..ea5b57b2b4719b 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2022-04-17-02-55-38.gh-issue-91625.80CrC7.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2022-04-17-02-55-38.gh-issue-91625.80CrC7.rst @@ -1 +1 @@ -Fixed a bug in which adaptive opcodes ignored any preceding ``EXTENDED_ARG``s on specialization failure. +Fixed a bug in which adaptive opcodes ignored any preceding ``EXTENDED_ARG``\ s on specialization failure. From 0886c1e52d4b4cf889bf32eaf841223531875516 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Sat, 16 Apr 2022 23:45:13 -0400 Subject: [PATCH 04/11] add LOAD_ATTR test --- Lib/test/test_descr.py | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 5d36cb98792ac6..93b53c5ac898ef 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1961,6 +1961,51 @@ def __delitem__(self, key): del a[0:10] self.assertEqual(a.delitem, (slice(0, 10))) + def test_load_attr_extended_arg(self): + class Numbers: + def __getattr__(self, attr): + return int(attr.lstrip("_")) + def number_attrs(Z): + return [ + Z._000, Z._001, Z._002, Z._003, Z._004, Z._005, Z._006, Z._007, + Z._008, Z._009, Z._010, Z._011, Z._012, Z._013, Z._014, Z._015, + Z._016, Z._017, Z._018, Z._019, Z._020, Z._021, Z._022, Z._023, + Z._024, Z._025, Z._026, Z._027, Z._028, Z._029, Z._030, Z._031, + Z._032, Z._033, Z._034, Z._035, Z._036, Z._037, Z._038, Z._039, + Z._040, Z._041, Z._042, Z._043, Z._044, Z._045, Z._046, Z._047, + Z._048, Z._049, Z._050, Z._051, Z._052, Z._053, Z._054, Z._055, + Z._056, Z._057, Z._058, Z._059, Z._060, Z._061, Z._062, Z._063, + Z._064, Z._065, Z._066, Z._067, Z._068, Z._069, Z._070, Z._071, + Z._072, Z._073, Z._074, Z._075, Z._076, Z._077, Z._078, Z._079, + Z._080, Z._081, Z._082, Z._083, Z._084, Z._085, Z._086, Z._087, + Z._088, Z._089, Z._090, Z._091, Z._092, Z._093, Z._094, Z._095, + Z._096, Z._097, Z._098, Z._099, Z._100, Z._101, Z._102, Z._103, + Z._104, Z._105, Z._106, Z._107, Z._108, Z._109, Z._110, Z._111, + Z._112, Z._113, Z._114, Z._115, Z._116, Z._117, Z._118, Z._119, + Z._120, Z._121, Z._122, Z._123, Z._124, Z._125, Z._126, Z._127, + Z._128, Z._129, Z._130, Z._131, Z._132, Z._133, Z._134, Z._135, + Z._136, Z._137, Z._138, Z._139, Z._140, Z._141, Z._142, Z._143, + Z._144, Z._145, Z._146, Z._147, Z._148, Z._149, Z._150, Z._151, + Z._152, Z._153, Z._154, Z._155, Z._156, Z._157, Z._158, Z._159, + Z._160, Z._161, Z._162, Z._163, Z._164, Z._165, Z._166, Z._167, + Z._168, Z._169, Z._170, Z._171, Z._172, Z._173, Z._174, Z._175, + Z._176, Z._177, Z._178, Z._179, Z._180, Z._181, Z._182, Z._183, + Z._184, Z._185, Z._186, Z._187, Z._188, Z._189, Z._190, Z._191, + Z._192, Z._193, Z._194, Z._195, Z._196, Z._197, Z._198, Z._199, + Z._200, Z._201, Z._202, Z._203, Z._204, Z._205, Z._206, Z._207, + Z._208, Z._209, Z._210, Z._211, Z._212, Z._213, Z._214, Z._215, + Z._216, Z._217, Z._218, Z._219, Z._220, Z._221, Z._222, Z._223, + Z._224, Z._225, Z._226, Z._227, Z._228, Z._229, Z._230, Z._231, + Z._232, Z._233, Z._234, Z._235, Z._236, Z._237, Z._238, Z._239, + Z._240, Z._241, Z._242, Z._243, Z._244, Z._245, Z._246, Z._247, + Z._248, Z._249, Z._250, Z._251, Z._252, Z._253, Z._254, Z._255, + Z._256, Z._257, Z._258, Z._259, Z._260, Z._261, Z._262, Z._263, + Z._264, Z._265, Z._266, Z._267, Z._268, Z._269, Z._270, Z._271, + Z._272, Z._273, Z._274, Z._275, Z._276, Z._277, Z._278, Z._279, + ] + for _ in range(30): + self.assertEqual(number_attrs(Numbers()), list(range(280))) + def test_methods(self): # Testing methods... class C(object): From 8634d60cd6a36b253f8dd47b78f4162ea31bc3b5 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Sun, 17 Apr 2022 00:08:49 -0400 Subject: [PATCH 05/11] Add test for LOAD_GLOBAL --- Lib/test/test_dynamic.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Lib/test/test_dynamic.py b/Lib/test/test_dynamic.py index 3ae090fd66ae25..f63111c25ba596 100644 --- a/Lib/test/test_dynamic.py +++ b/Lib/test/test_dynamic.py @@ -133,6 +133,17 @@ def test_eval_gives_lambda_custom_globals(self): self.assertEqual(foo(), 7) + def test_load_global_specialization_failure_keeps_oparg(self): + class MyGlobals(dict): + def __missing__(self, key): + return int(key.removeprefix("_number_")) + + code = ("lambda: [" + + ", ".join(f"_number_{i}" for i in range(1000)) + + "]") + func = eval(code, MyGlobals()) + numbers = func() + self.assertEqual(numbers, list(range(1000))) if __name__ == "__main__": unittest.main() From dafe1f7c3d16c3a29db559e7400cc2bfd3bc188b Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Sun, 17 Apr 2022 00:11:23 -0400 Subject: [PATCH 06/11] Link back to github issue --- Lib/test/test_descr.py | 1 + Lib/test/test_dynamic.py | 1 + Lib/test/test_unpack.py | 1 + 3 files changed, 3 insertions(+) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 93b53c5ac898ef..c93d3ed2097218 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1962,6 +1962,7 @@ def __delitem__(self, key): self.assertEqual(a.delitem, (slice(0, 10))) def test_load_attr_extended_arg(self): + # https://github.com/python/cpython/issues/91625 class Numbers: def __getattr__(self, attr): return int(attr.lstrip("_")) diff --git a/Lib/test/test_dynamic.py b/Lib/test/test_dynamic.py index f63111c25ba596..f76e8a3cea94a7 100644 --- a/Lib/test/test_dynamic.py +++ b/Lib/test/test_dynamic.py @@ -134,6 +134,7 @@ def test_eval_gives_lambda_custom_globals(self): self.assertEqual(foo(), 7) def test_load_global_specialization_failure_keeps_oparg(self): + # https://github.com/python/cpython/issues/91625 class MyGlobals(dict): def __missing__(self, key): return int(key.removeprefix("_number_")) diff --git a/Lib/test/test_unpack.py b/Lib/test/test_unpack.py index 528df533fe354f..d41166f99c097b 100644 --- a/Lib/test/test_unpack.py +++ b/Lib/test/test_unpack.py @@ -184,6 +184,7 @@ def unpack_400(x): class TestCornerCases(unittest.TestCase): def test_extended_oparg_not_ignored(self): + # https://github.com/python/cpython/issues/91625 for _ in range(30): y = unpack_400(range(400)) self.assertEqual(y, 399) From 754ade4c065bf66180d7a64683d2cd9938d2e58a Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Sun, 17 Apr 2022 00:31:45 -0400 Subject: [PATCH 07/11] NOTRACE_DISPATCH_SAME_OPARG --- Python/ceval.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index 05dd27f2689889..f523e52fe01166 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1351,12 +1351,10 @@ eval_frame_handle_pending(PyThreadState *tstate) DISPATCH_GOTO(); \ } -#define DISPATCH_SAME_OPARG() \ +#define NOTRACE_DISPATCH_SAME_OPARG() \ { \ opcode = _Py_OPCODE(*next_instr); \ PRE_DISPATCH_GOTO(); \ - assert(cframe.use_tracing == 0 || cframe.use_tracing == 255); \ - opcode |= cframe.use_tracing OR_DTRACE_LINE; \ DISPATCH_GOTO(); \ } @@ -2167,7 +2165,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_BinarySubscr(container, sub, next_instr) < 0) { goto error; } - DISPATCH_SAME_OPARG(); + NOTRACE_DISPATCH_SAME_OPARG(); } else { STAT_INC(BINARY_SUBSCR, deferred); @@ -2332,7 +2330,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_StoreSubscr(container, sub, next_instr) < 0) { goto error; } - DISPATCH_SAME_OPARG(); + NOTRACE_DISPATCH_SAME_OPARG(); } else { STAT_INC(STORE_SUBSCR, deferred); @@ -2822,7 +2820,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *seq = TOP(); next_instr--; _Py_Specialize_UnpackSequence(seq, next_instr, oparg); - DISPATCH_SAME_OPARG(); + NOTRACE_DISPATCH_SAME_OPARG(); } else { STAT_INC(UNPACK_SEQUENCE, deferred); @@ -3065,7 +3063,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name) < 0) { goto error; } - DISPATCH_SAME_OPARG(); + NOTRACE_DISPATCH_SAME_OPARG(); } else { STAT_INC(LOAD_GLOBAL, deferred); @@ -3490,7 +3488,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_LoadAttr(owner, next_instr, name) < 0) { goto error; } - DISPATCH_SAME_OPARG(); + NOTRACE_DISPATCH_SAME_OPARG(); } else { STAT_INC(LOAD_ATTR, deferred); @@ -3599,7 +3597,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_StoreAttr(owner, next_instr, name) < 0) { goto error; } - DISPATCH_SAME_OPARG(); + NOTRACE_DISPATCH_SAME_OPARG(); } else { STAT_INC(STORE_ATTR, deferred); @@ -3727,7 +3725,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *left = SECOND(); next_instr--; _Py_Specialize_CompareOp(left, right, next_instr, oparg); - DISPATCH_SAME_OPARG(); + NOTRACE_DISPATCH_SAME_OPARG(); } else { STAT_INC(COMPARE_OP, deferred); @@ -4532,7 +4530,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_LoadMethod(owner, next_instr, name) < 0) { goto error; } - DISPATCH_SAME_OPARG(); + NOTRACE_DISPATCH_SAME_OPARG(); } else { STAT_INC(LOAD_METHOD, deferred); @@ -4806,7 +4804,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (err < 0) { goto error; } - DISPATCH_SAME_OPARG(); + NOTRACE_DISPATCH_SAME_OPARG(); } else { STAT_INC(PRECALL, deferred); @@ -4827,7 +4825,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (err < 0) { goto error; } - DISPATCH_SAME_OPARG(); + NOTRACE_DISPATCH_SAME_OPARG(); } else { STAT_INC(CALL, deferred); @@ -5554,7 +5552,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *rhs = TOP(); next_instr--; _Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg, &GETLOCAL(0)); - DISPATCH_SAME_OPARG(); + NOTRACE_DISPATCH_SAME_OPARG(); } else { STAT_INC(BINARY_OP, deferred); @@ -5573,11 +5571,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(EXTENDED_ARG) { assert(oparg); - int oldoparg = oparg; - NEXTOPARG(); - oparg |= oldoparg << 8; - PRE_DISPATCH_GOTO(); - DISPATCH_GOTO(); + oparg <<= 8; + oparg |= _Py_OPARG(*next_instr); + NOTRACE_DISPATCH_SAME_OPARG(); } TARGET(CACHE) { From 784882cd0ee529c86846743daa782f80aeadd13e Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Sun, 17 Apr 2022 00:33:21 -0400 Subject: [PATCH 08/11] whitespace from patchcheck --- Lib/test/test_descr.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index c93d3ed2097218..3b36f65b587f28 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4481,8 +4481,8 @@ def __getattr__(self, attr): raise RuntimeError(f"Premature access to sys.stdout.{attr}") with redirect_stdout(StdoutGuard()): - with self.assertRaises(RuntimeError): - print("Oops!") + with self.assertRaises(RuntimeError): + print("Oops!") def test_vicious_descriptor_nonsense(self): # Testing vicious_descriptor_nonsense... From 760df1538620eafb9c425e9e9ba73c9feeaaedf2 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Sun, 17 Apr 2022 01:23:48 -0400 Subject: [PATCH 09/11] make sure the tests actually failed before the change --- Lib/test/test_descr.py | 1 + Lib/test/test_dynamic.py | 12 ++++++------ Lib/test/test_unpack.py | 1 + 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 3b36f65b587f28..0e264a6355fd6d 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -2004,6 +2004,7 @@ def number_attrs(Z): Z._264, Z._265, Z._266, Z._267, Z._268, Z._269, Z._270, Z._271, Z._272, Z._273, Z._274, Z._275, Z._276, Z._277, Z._278, Z._279, ] + # Warm up the the function for quickening (PEP 659) for _ in range(30): self.assertEqual(number_attrs(Numbers()), list(range(280))) diff --git a/Lib/test/test_dynamic.py b/Lib/test/test_dynamic.py index f76e8a3cea94a7..3e0fcf4d158f8a 100644 --- a/Lib/test/test_dynamic.py +++ b/Lib/test/test_dynamic.py @@ -139,12 +139,12 @@ class MyGlobals(dict): def __missing__(self, key): return int(key.removeprefix("_number_")) - code = ("lambda: [" + - ", ".join(f"_number_{i}" for i in range(1000)) + - "]") - func = eval(code, MyGlobals()) - numbers = func() - self.assertEqual(numbers, list(range(1000))) + code = "lambda: " + "+".join(f"_number_{i}" for i in range(1000)) + sum_1000 = eval(code, MyGlobals()) + expected = sum(range(1000)) + # Warm up the the function for quickening (PEP 659) + for _ in range(30): + self.assertEqual(sum_1000(), expected) if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_unpack.py b/Lib/test/test_unpack.py index d41166f99c097b..722859a7fcea09 100644 --- a/Lib/test/test_unpack.py +++ b/Lib/test/test_unpack.py @@ -185,6 +185,7 @@ def unpack_400(x): class TestCornerCases(unittest.TestCase): def test_extended_oparg_not_ignored(self): # https://github.com/python/cpython/issues/91625 + # Warm up the the function for quickening (PEP 659) for _ in range(30): y = unpack_400(range(400)) self.assertEqual(y, 399) From 64d49cdd16a451468a84f324a17a0cefcbef3007 Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Sun, 17 Apr 2022 12:33:19 -0400 Subject: [PATCH 10/11] generate the test code --- Lib/test/test_descr.py | 43 +++++------------------------------------ Lib/test/test_unpack.py | 8 ++++++++ 2 files changed, 13 insertions(+), 38 deletions(-) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 0e264a6355fd6d..378ff5227e221a 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1966,44 +1966,11 @@ def test_load_attr_extended_arg(self): class Numbers: def __getattr__(self, attr): return int(attr.lstrip("_")) - def number_attrs(Z): - return [ - Z._000, Z._001, Z._002, Z._003, Z._004, Z._005, Z._006, Z._007, - Z._008, Z._009, Z._010, Z._011, Z._012, Z._013, Z._014, Z._015, - Z._016, Z._017, Z._018, Z._019, Z._020, Z._021, Z._022, Z._023, - Z._024, Z._025, Z._026, Z._027, Z._028, Z._029, Z._030, Z._031, - Z._032, Z._033, Z._034, Z._035, Z._036, Z._037, Z._038, Z._039, - Z._040, Z._041, Z._042, Z._043, Z._044, Z._045, Z._046, Z._047, - Z._048, Z._049, Z._050, Z._051, Z._052, Z._053, Z._054, Z._055, - Z._056, Z._057, Z._058, Z._059, Z._060, Z._061, Z._062, Z._063, - Z._064, Z._065, Z._066, Z._067, Z._068, Z._069, Z._070, Z._071, - Z._072, Z._073, Z._074, Z._075, Z._076, Z._077, Z._078, Z._079, - Z._080, Z._081, Z._082, Z._083, Z._084, Z._085, Z._086, Z._087, - Z._088, Z._089, Z._090, Z._091, Z._092, Z._093, Z._094, Z._095, - Z._096, Z._097, Z._098, Z._099, Z._100, Z._101, Z._102, Z._103, - Z._104, Z._105, Z._106, Z._107, Z._108, Z._109, Z._110, Z._111, - Z._112, Z._113, Z._114, Z._115, Z._116, Z._117, Z._118, Z._119, - Z._120, Z._121, Z._122, Z._123, Z._124, Z._125, Z._126, Z._127, - Z._128, Z._129, Z._130, Z._131, Z._132, Z._133, Z._134, Z._135, - Z._136, Z._137, Z._138, Z._139, Z._140, Z._141, Z._142, Z._143, - Z._144, Z._145, Z._146, Z._147, Z._148, Z._149, Z._150, Z._151, - Z._152, Z._153, Z._154, Z._155, Z._156, Z._157, Z._158, Z._159, - Z._160, Z._161, Z._162, Z._163, Z._164, Z._165, Z._166, Z._167, - Z._168, Z._169, Z._170, Z._171, Z._172, Z._173, Z._174, Z._175, - Z._176, Z._177, Z._178, Z._179, Z._180, Z._181, Z._182, Z._183, - Z._184, Z._185, Z._186, Z._187, Z._188, Z._189, Z._190, Z._191, - Z._192, Z._193, Z._194, Z._195, Z._196, Z._197, Z._198, Z._199, - Z._200, Z._201, Z._202, Z._203, Z._204, Z._205, Z._206, Z._207, - Z._208, Z._209, Z._210, Z._211, Z._212, Z._213, Z._214, Z._215, - Z._216, Z._217, Z._218, Z._219, Z._220, Z._221, Z._222, Z._223, - Z._224, Z._225, Z._226, Z._227, Z._228, Z._229, Z._230, Z._231, - Z._232, Z._233, Z._234, Z._235, Z._236, Z._237, Z._238, Z._239, - Z._240, Z._241, Z._242, Z._243, Z._244, Z._245, Z._246, Z._247, - Z._248, Z._249, Z._250, Z._251, Z._252, Z._253, Z._254, Z._255, - Z._256, Z._257, Z._258, Z._259, Z._260, Z._261, Z._262, Z._263, - Z._264, Z._265, Z._266, Z._267, Z._268, Z._269, Z._270, Z._271, - Z._272, Z._273, Z._274, Z._275, Z._276, Z._277, Z._278, Z._279, - ] + attrs = ", ".join(f"Z._{n:03d}" for n in range(280)) + code = f"def number_attrs(Z):\n return [ {attrs} ]" + ns = {} + exec(code, ns) + number_attrs = ns["number_attrs"] # Warm up the the function for quickening (PEP 659) for _ in range(30): self.assertEqual(number_attrs(Numbers()), list(range(280))) diff --git a/Lib/test/test_unpack.py b/Lib/test/test_unpack.py index 722859a7fcea09..a72c2c66257c88 100644 --- a/Lib/test/test_unpack.py +++ b/Lib/test/test_unpack.py @@ -185,6 +185,14 @@ def unpack_400(x): class TestCornerCases(unittest.TestCase): def test_extended_oparg_not_ignored(self): # https://github.com/python/cpython/issues/91625 + target = "(" + "y,"*400 + ")" + code = f"""def unpack_400(x): + {target} = x + return y + """ + ns = {} + exec(code, ns) + unpack_400 = ns["unpack_400"] # Warm up the the function for quickening (PEP 659) for _ in range(30): y = unpack_400(range(400)) From 32b246679d89f74579e57c36ee993b767408e41b Mon Sep 17 00:00:00 2001 From: sweeneyde Date: Sun, 17 Apr 2022 12:36:27 -0400 Subject: [PATCH 11/11] Remove unused code --- Lib/test/test_unpack.py | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/Lib/test/test_unpack.py b/Lib/test/test_unpack.py index a72c2c66257c88..f5ca1d455b5c6f 100644 --- a/Lib/test/test_unpack.py +++ b/Lib/test/test_unpack.py @@ -150,37 +150,6 @@ def load_tests(loader, tests, pattern): tests.addTest(doctest.DocTestSuite()) return tests -def unpack_400(x): - # UNPACK_SEQUENCE 400 - # is actually - # EXTENDED_ARG 1 - # UNPACK_SEQUENCE 144 - ( - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, y,y,y,y,y, - ) = x - return y class TestCornerCases(unittest.TestCase): def test_extended_oparg_not_ignored(self):