| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1748,28 +1748,80 @@ class Subclass(BaseException, self.module.StateAccessType): | |||
| 1748 | 1748 | ||
| 1749 | 1749 | class Test_Pep523API(unittest.TestCase): | |
| 1750 | 1750 | ||
| 1751 | - def do_test(self, func): | ||
| 1752 | - calls = [] | ||
| 1751 | + def do_test(self, func, names): | ||
| 1752 | + actual_calls = [] | ||
| 1753 | 1753 | start = SUFFICIENT_TO_DEOPT_AND_SPECIALIZE | |
| 1754 | 1754 | count = start + SUFFICIENT_TO_DEOPT_AND_SPECIALIZE | |
| 1755 | - for i in range(count): | ||
| 1756 | - if i == start: | ||
| 1757 | - _testinternalcapi.set_eval_frame_record(calls) | ||
| 1758 | - func() | ||
| 1759 | - _testinternalcapi.set_eval_frame_default() | ||
| 1760 | - self.assertEqual(len(calls), SUFFICIENT_TO_DEOPT_AND_SPECIALIZE) | ||
| 1761 | - for name in calls: | ||
| 1762 | - self.assertEqual(name, func.__name__) | ||
| 1763 | - | ||
| 1764 | - def test_pep523_with_specialization_simple(self): | ||
| 1765 | - def func1(): | ||
| 1766 | - pass | ||
| 1767 | - self.do_test(func1) | ||
| 1755 | + try: | ||
| 1756 | + for i in range(count): | ||
| 1757 | + if i == start: | ||
| 1758 | + _testinternalcapi.set_eval_frame_record(actual_calls) | ||
| 1759 | + func() | ||
| 1760 | + finally: | ||
| 1761 | + _testinternalcapi.set_eval_frame_default() | ||
| 1762 | + expected_calls = names * SUFFICIENT_TO_DEOPT_AND_SPECIALIZE | ||
| 1763 | + self.assertEqual(len(expected_calls), len(actual_calls)) | ||
| 1764 | + for expected, actual in zip(expected_calls, actual_calls, strict=True): | ||
| 1765 | + self.assertEqual(expected, actual) | ||
| 1766 | + | ||
| 1767 | + def test_inlined_binary_subscr(self): | ||
| 1768 | + class C: | ||
| 1769 | + def __getitem__(self, other): | ||
| 1770 | + return None | ||
| 1771 | + def func(): | ||
| 1772 | + C()[42] | ||
| 1773 | + names = ["func", "__getitem__"] | ||
| 1774 | + self.do_test(func, names) | ||
| 1768 | 1775 | ||
| 1769 | - def test_pep523_with_specialization_with_default(self): | ||
| 1770 | - def func2(x=None): | ||
| 1776 | + def test_inlined_call(self): | ||
| 1777 | + def inner(x=42): | ||
| 1778 | + pass | ||
| 1779 | + def func(): | ||
| 1780 | + inner() | ||
| 1781 | + inner(42) | ||
| 1782 | + names = ["func", "inner", "inner"] | ||
| 1783 | + self.do_test(func, names) | ||
| 1784 | + | ||
| 1785 | + def test_inlined_call_function_ex(self): | ||
| 1786 | + def inner(x): | ||
| 1771 | 1787 | pass | |
| 1772 | - self.do_test(func2) | ||
| 1788 | + def func(): | ||
| 1789 | + inner(*[42]) | ||
| 1790 | + names = ["func", "inner"] | ||
| 1791 | + self.do_test(func, names) | ||
| 1792 | + | ||
| 1793 | + def test_inlined_for_iter(self): | ||
| 1794 | + def gen(): | ||
| 1795 | + yield 42 | ||
| 1796 | + def func(): | ||
| 1797 | + for _ in gen(): | ||
| 1798 | + pass | ||
| 1799 | + names = ["func", "gen", "gen", "gen"] | ||
| 1800 | + self.do_test(func, names) | ||
| 1801 | + | ||
| 1802 | + def test_inlined_load_attr(self): | ||
| 1803 | + class C: | ||
| 1804 | + @property | ||
| 1805 | + def a(self): | ||
| 1806 | + return 42 | ||
| 1807 | + class D: | ||
| 1808 | + def __getattribute__(self, name): | ||
| 1809 | + return 42 | ||
| 1810 | + def func(): | ||
| 1811 | + C().a | ||
| 1812 | + D().a | ||
| 1813 | + names = ["func", "a", "__getattribute__"] | ||
| 1814 | + self.do_test(func, names) | ||
| 1815 | + | ||
| 1816 | + def test_inlined_send(self): | ||
| 1817 | + def inner(): | ||
| 1818 | + yield 42 | ||
| 1819 | + def outer(): | ||
| 1820 | + yield from inner() | ||
| 1821 | + def func(): | ||
| 1822 | + list(outer()) | ||
| 1823 | + names = ["func", "outer", "outer", "inner", "inner", "outer", "inner"] | ||
| 1824 | + self.do_test(func, names) | ||
| 1773 | 1825 | ||
| 1774 | 1826 | ||
| 1775 | 1827 | if __name__ == "__main__": | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,2 @@ | |||
| 1 | + Fix an issue where some :term:`bytecode` instructions could ignore | ||
| 2 | + :pep:`523` when "inlining" calls. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -494,6 +494,7 @@ dummy_func( | |||
| 494 | 494 | } | |
| 495 | 495 | ||
| 496 | 496 | inst(BINARY_SUBSCR_GETITEM, (unused/1, container, sub -- unused)) { | |
| 497 | + DEOPT_IF(tstate->interp->eval_frame, BINARY_SUBSCR); | ||
| 497 | 498 | PyTypeObject *tp = Py_TYPE(container); | |
| 498 | 499 | DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE), BINARY_SUBSCR); | |
| 499 | 500 | PyHeapTypeObject *ht = (PyHeapTypeObject *)tp; | |
@@ -830,8 +831,9 @@ dummy_func( | |||
| 830 | 831 | DECREMENT_ADAPTIVE_COUNTER(cache->counter); | |
| 831 | 832 | #endif /* ENABLE_SPECIALIZATION */ | |
| 832 | 833 | assert(frame != &entry_frame); | |
| 833 | - if ((Py_TYPE(receiver) == &PyGen_Type || | ||
| 834 | - Py_TYPE(receiver) == &PyCoro_Type) && ((PyGenObject *)receiver)->gi_frame_state < FRAME_EXECUTING) | ||
| 834 | + if ((tstate->interp->eval_frame == NULL) && | ||
| 835 | + (Py_TYPE(receiver) == &PyGen_Type || Py_TYPE(receiver) == &PyCoro_Type) && | ||
| 836 | + ((PyGenObject *)receiver)->gi_frame_state < FRAME_EXECUTING) | ||
| 835 | 837 | { | |
| 836 | 838 | PyGenObject *gen = (PyGenObject *)receiver; | |
| 837 | 839 | _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; | |
@@ -867,6 +869,7 @@ dummy_func( | |||
| 867 | 869 | } | |
| 868 | 870 | ||
| 869 | 871 | inst(SEND_GEN, (unused/1, receiver, v -- receiver, unused)) { | |
| 872 | + DEOPT_IF(tstate->interp->eval_frame, SEND); | ||
| 870 | 873 | PyGenObject *gen = (PyGenObject *)receiver; | |
| 871 | 874 | DEOPT_IF(Py_TYPE(gen) != &PyGen_Type && | |
| 872 | 875 | Py_TYPE(gen) != &PyCoro_Type, SEND); | |
@@ -2331,6 +2334,7 @@ dummy_func( | |||
| 2331 | 2334 | } | |
| 2332 | 2335 | ||
| 2333 | 2336 | inst(FOR_ITER_GEN, (unused/1, iter -- iter, unused)) { | |
| 2337 | + DEOPT_IF(tstate->interp->eval_frame, FOR_ITER); | ||
| 2334 | 2338 | PyGenObject *gen = (PyGenObject *)iter; | |
| 2335 | 2339 | DEOPT_IF(Py_TYPE(gen) != &PyGen_Type, FOR_ITER); | |
| 2336 | 2340 | DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, FOR_ITER); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -105,6 +105,7 @@ | |||
| 105 | 105 | ||
| 106 | 106 | #define DISPATCH_INLINED(NEW_FRAME) \ | |
| 107 | 107 | do { \ | |
| 108 | + assert(tstate->interp->eval_frame == NULL); \ | ||
| 108 | 109 | _PyFrame_SetStackPointer(frame, stack_pointer); \ | |
| 109 | 110 | frame->prev_instr = next_instr - 1; \ | |
| 110 | 111 | (NEW_FRAME)->previous = frame; \ | |
| Back | FazBrowse Home | New Git URL |
0 commit comments