Skip to content

Commit 35a47ee

Browse files
committed
Merge remote-tracking branch 'upstream/main' into conditional_jump_only_forward
2 parents e31029b + a91f255 commit 35a47ee

File tree

8 files changed

+79
-45
lines changed

8 files changed

+79
-45
lines changed

Doc/library/stdtypes.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4694,7 +4694,9 @@ values are hashable, so that ``(key, value)`` pairs are unique and hashable,
46944694
then the items view is also set-like. (Values views are not treated as set-like
46954695
since the entries are generally not unique.) For set-like views, all of the
46964696
operations defined for the abstract base class :class:`collections.abc.Set` are
4697-
available (for example, ``==``, ``<``, or ``^``).
4697+
available (for example, ``==``, ``<``, or ``^``). While using set operators,
4698+
set-like views accept any iterable as the other operand, unlike sets which only
4699+
accept sets as the input.
46984700

46994701
An example of dictionary view usage::
47004702

@@ -4726,6 +4728,8 @@ An example of dictionary view usage::
47264728
{'bacon'}
47274729
>>> keys ^ {'sausage', 'juice'}
47284730
{'juice', 'sausage', 'bacon', 'spam'}
4731+
>>> keys | ['juice', 'juice', 'juice']
4732+
{'juice', 'sausage', 'bacon', 'spam', 'eggs'}
47294733

47304734
>>> # get back a read-only proxy for the original dictionary
47314735
>>> values.mapping

Lib/test/test_peepholer.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -891,7 +891,8 @@ def test_conditional_jump_forward_non_const_condition(self):
891891
self.cfg_optimization_test(insts, expected, consts=list(range(5)))
892892

893893
def test_conditional_jump_forward_const_condition(self):
894-
# The unreachable branch of the jump is removed
894+
# The unreachable branch of the jump is removed, the jump
895+
# becomes redundant and is replaced by a NOP (for the lineno)
895896

896897
insts = [
897898
('LOAD_CONST', 3, 11),
@@ -902,8 +903,7 @@ def test_conditional_jump_forward_const_condition(self):
902903
]
903904
expected = [
904905
('NOP', None, 11),
905-
('JUMP', lbl := self.Label(), 12),
906-
lbl,
906+
('NOP', None, 12),
907907
('LOAD_CONST', '3', 14)
908908
]
909909
self.cfg_optimization_test(insts, expected, consts=list(range(5)))

Lib/test/test_perf_profiler.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def baz():
108108
script = make_script(script_dir, "perftest", code)
109109
with subprocess.Popen(
110110
[sys.executable, "-Xperf", script],
111-
universal_newlines=True,
111+
text=True,
112112
stderr=subprocess.PIPE,
113113
stdout=subprocess.PIPE,
114114
) as process:
@@ -157,7 +157,7 @@ def baz():
157157
script = make_script(script_dir, "perftest", code)
158158
with subprocess.Popen(
159159
[sys.executable, script],
160-
universal_newlines=True,
160+
text=True,
161161
stderr=subprocess.PIPE,
162162
stdout=subprocess.PIPE,
163163
) as process:
@@ -211,7 +211,7 @@ def is_unwinding_reliable():
211211
def perf_command_works():
212212
try:
213213
cmd = ["perf", "--help"]
214-
stdout = subprocess.check_output(cmd, universal_newlines=True)
214+
stdout = subprocess.check_output(cmd, text=True)
215215
except (subprocess.SubprocessError, OSError):
216216
return False
217217

@@ -237,7 +237,7 @@ def perf_command_works():
237237
'print("hello")',
238238
)
239239
stdout = subprocess.check_output(
240-
cmd, cwd=script_dir, universal_newlines=True, stderr=subprocess.STDOUT
240+
cmd, cwd=script_dir, text=True, stderr=subprocess.STDOUT
241241
)
242242
except (subprocess.SubprocessError, OSError):
243243
return False

Lib/test/test_typing.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7143,6 +7143,7 @@ def test_special_attrs(self):
71437143
typing.Self: 'Self',
71447144
# Subscribed special forms
71457145
typing.Annotated[Any, "Annotation"]: 'Annotated',
7146+
typing.Annotated[int, 'Annotation']: 'Annotated',
71467147
typing.ClassVar[Any]: 'ClassVar',
71477148
typing.Concatenate[Any, SpecialAttrsP]: 'Concatenate',
71487149
typing.Final[Any]: 'Final',

Lib/typing.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2101,7 +2101,7 @@ def __init__(self, origin, metadata):
21012101
if isinstance(origin, _AnnotatedAlias):
21022102
metadata = origin.__metadata__ + metadata
21032103
origin = origin.__origin__
2104-
super().__init__(origin, origin)
2104+
super().__init__(origin, origin, name='Annotated')
21052105
self.__metadata__ = metadata
21062106

21072107
def copy_with(self, params):
@@ -2134,6 +2134,9 @@ def __getattr__(self, attr):
21342134
return 'Annotated'
21352135
return super().__getattr__(attr)
21362136

2137+
def __mro_entries__(self, bases):
2138+
return (self.__origin__,)
2139+
21372140

21382141
class Annotated:
21392142
"""Add context specific metadata to a type.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
In :mod:`typing`, fix missing field ``name`` and incorrect ``__module__`` in _AnnotatedAlias.

Objects/exception_handling_notes.txt

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -43,33 +43,36 @@ SETUP_FINALLY and POP_BLOCK.
4343
In 3.11, the SETUP_FINALLY and POP_BLOCK are eliminated, replaced with
4444
a table to determine where to jump to when an exception is raised.
4545

46-
2 0 NOP
47-
48-
3 2 LOAD_GLOBAL 0 (g)
49-
4 LOAD_CONST 1 (0)
50-
6 CALL_NO_KW 1
51-
8 POP_TOP
52-
10 LOAD_CONST 0 (None)
53-
12 RETURN_VALUE
54-
>> 14 PUSH_EXC_INFO
55-
56-
4 16 POP_TOP
57-
18 POP_TOP
58-
20 POP_TOP
59-
60-
5 22 POP_EXCEPT
61-
24 LOAD_CONST 2 ('fail')
62-
26 RETURN_VALUE
63-
>> 28 POP_EXCEPT_AND_RERAISE
46+
1 0 RESUME 0
47+
48+
2 2 NOP
49+
50+
3 4 LOAD_GLOBAL 1 (NULL + g)
51+
16 LOAD_CONST 1 (0)
52+
18 PRECALL 1
53+
22 CALL 1
54+
32 POP_TOP
55+
34 LOAD_CONST 0 (None)
56+
36 RETURN_VALUE
57+
>> 38 PUSH_EXC_INFO
58+
59+
4 40 POP_TOP
60+
61+
5 42 POP_EXCEPT
62+
44 LOAD_CONST 2 ('fail')
63+
46 RETURN_VALUE
64+
>> 48 COPY 3
65+
50 POP_EXCEPT
66+
52 RERAISE 1
6467
ExceptionTable:
65-
2 to 8 -> 14 [0]
66-
14 to 20 -> 28 [3] lasti
68+
4 to 32 -> 38 [0]
69+
38 to 40 -> 48 [1] lasti
6770

68-
(Note this code is from an early 3.11 alpha, the NOP may well have be removed before release).
71+
(Note this code is from 3.11, later versions may have slightly different bytecode.)
6972

7073
If an instruction raises an exception then its offset is used to find the target to jump to.
71-
For example, the CALL_NO_KW at offset 6, falls into the range 2 to 8.
72-
So, if g() raises an exception, then control jumps to offset 14.
74+
For example, the CALL at offset 22, falls into the range 4 to 32.
75+
So, if g() raises an exception, then control jumps to offset 38.
7376

7477

7578
Unwinding
@@ -84,9 +87,9 @@ This information is stored in the exception table, described below.
8487
If there is no relevant entry, the exception bubbles up to the caller.
8588

8689
If there is an entry, then:
87-
1. pop values from the stack until it matches the stack depth for the handler,
90+
1. pop values from the stack until it matches the stack depth for the handler.
8891
2. if 'lasti' is true, then push the offset that the exception was raised at.
89-
3. push the exception to the stack as three values: traceback, value, type,
92+
3. push the exception to the stack.
9093
4. jump to the target offset and resume execution.
9194

9295

Python/compile.c

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7376,6 +7376,9 @@ mark_cold(basicblock *entryblock) {
73767376
return 0;
73777377
}
73787378

7379+
static int
7380+
remove_redundant_jumps(cfg_builder *g);
7381+
73797382
static int
73807383
push_cold_blocks_to_end(cfg_builder *g, int code_flags) {
73817384
basicblock *entryblock = g->g_entryblock;
@@ -7445,6 +7448,12 @@ push_cold_blocks_to_end(cfg_builder *g, int code_flags) {
74457448
}
74467449
assert(b != NULL && b->b_next == NULL);
74477450
b->b_next = cold_blocks;
7451+
7452+
if (cold_blocks != NULL) {
7453+
if (remove_redundant_jumps(g) < 0) {
7454+
return -1;
7455+
}
7456+
}
74487457
return 0;
74497458
}
74507459

@@ -8277,9 +8286,6 @@ trim_unused_consts(basicblock *entryblock, PyObject *consts);
82778286
static int
82788287
duplicate_exits_without_lineno(cfg_builder *g);
82798288

8280-
static int
8281-
extend_block(basicblock *bb);
8282-
82838289
static int *
82848290
build_cellfixedoffsets(struct compiler *c)
82858291
{
@@ -8484,6 +8490,21 @@ propagate_line_numbers(basicblock *entryblock);
84848490
static void
84858491
eliminate_empty_basic_blocks(cfg_builder *g);
84868492

8493+
#ifndef NDEBUG
8494+
static bool
8495+
no_redundant_jumps(cfg_builder *g) {
8496+
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
8497+
struct instr *last = basicblock_last_instr(b);
8498+
if (last != NULL) {
8499+
if (last->i_opcode == JUMP || last->i_opcode == JUMP_NO_INTERRUPT) {
8500+
assert(last->i_target != b->b_next);
8501+
return false;
8502+
}
8503+
}
8504+
}
8505+
return true;
8506+
}
8507+
#endif
84878508

84888509
static int
84898510
remove_redundant_jumps(cfg_builder *g) {
@@ -8600,8 +8621,8 @@ assemble(struct compiler *c, int addNone)
86008621
if (trim_unused_consts(g->g_entryblock, consts)) {
86018622
goto error;
86028623
}
8603-
if (duplicate_exits_without_lineno(g)) {
8604-
return NULL;
8624+
if (duplicate_exits_without_lineno(g) < 0) {
8625+
goto error;
86058626
}
86068627
propagate_line_numbers(g->g_entryblock);
86078628
guarantee_lineno_for_exits(g->g_entryblock, c->u->u_firstlineno);
@@ -8620,10 +8641,6 @@ assemble(struct compiler *c, int addNone)
86208641
if (push_cold_blocks_to_end(g, code_flags) < 0) {
86218642
goto error;
86228643
}
8623-
8624-
if (remove_redundant_jumps(g) < 0) {
8625-
goto error;
8626-
}
86278644
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
86288645
clean_basic_block(b);
86298646
}
@@ -8637,6 +8654,8 @@ assemble(struct compiler *c, int addNone)
86378654
goto error;
86388655
}
86398656

8657+
assert(no_redundant_jumps(g));
8658+
86408659
/* Can't modify the bytecode after computing jump offsets. */
86418660
assemble_jump_offsets(g->g_entryblock);
86428661

@@ -9498,7 +9517,7 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
94989517
}
94999518
}
95009519
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
9501-
if (extend_block(b)) {
9520+
if (extend_block(b) < 0) {
95029521
return -1;
95039522
}
95049523
}
@@ -9510,7 +9529,7 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
95109529
assert(b->b_predecessors == 0);
95119530
}
95129531
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
9513-
if (extend_block(b)) {
9532+
if (extend_block(b) < 0) {
95149533
return -1;
95159534
}
95169535
}
@@ -9527,6 +9546,9 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
95279546
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
95289547
clean_basic_block(b);
95299548
}
9549+
if (remove_redundant_jumps(g) < 0) {
9550+
return -1;
9551+
}
95309552
return 0;
95319553
}
95329554

0 commit comments

Comments
 (0)