Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf02fa64

Browse files
authored
GH-100762: Don't callgen.throw() ingen.close(), unless necessary. (GH-101013)
* Store exception stack depth in YIELD_VALUE's oparg and use it avoid expensive gen.throw() in gen.close() where possible.
1 parentdaec3a4 commitf02fa64

File tree

9 files changed

+39
-12
lines changed

9 files changed

+39
-12
lines changed

‎Doc/library/dis.rst‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,10 @@ iterations of the loop.
700700
Yields ``STACK.pop()`` from a:term:`generator`.
701701

702702
..versionchanged::3.11
703-
oparg set to be the stack depth, for efficient handling on frames.
703+
oparg set to be the stack depth.
704+
705+
..versionchanged::3.12
706+
oparg set to be the exception block depth, for efficient closing of generators.
704707

705708

706709
..opcode::SETUP_ANNOTATIONS

‎Lib/importlib/_bootstrap_external.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,8 @@ def _write_atomic(path, data, mode=0o666):
429429
# Python 3.12a1 3513 (Add CALL_INTRINSIC_1 instruction, removed STOPITERATION_ERROR, PRINT_EXPR, IMPORT_STAR)
430430
# Python 3.12a1 3514 (Remove ASYNC_GEN_WRAP, LIST_TO_TUPLE, and UNARY_POSITIVE)
431431
# Python 3.12a1 3515 (Embed jump mask in COMPARE_OP oparg)
432-
# Python 3.12a1 3516 (Add COMAPRE_AND_BRANCH instruction)
432+
# Python 3.12a1 3516 (Add COMPARE_AND_BRANCH instruction)
433+
# Python 3.12a1 3517 (Change YIELD_VALUE oparg to exception block depth)
433434

434435
# Python 3.13 will start with 3550
435436

@@ -442,7 +443,7 @@ def _write_atomic(path, data, mode=0o666):
442443
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
443444
# in PC/launcher.c must also be updated.
444445

445-
MAGIC_NUMBER= (3516).to_bytes(2,'little')+b'\r\n'
446+
MAGIC_NUMBER= (3517).to_bytes(2,'little')+b'\r\n'
446447

447448
_RAW_MAGIC_NUMBER=int.from_bytes(MAGIC_NUMBER,'little')# For import.c
448449

‎Lib/test/test_dis.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ async def _asyncwith(c):
492492
GET_AWAITABLE 1
493493
LOAD_CONST 0 (None)
494494
>> SEND 3 (to 22)
495-
YIELD_VALUE3
495+
YIELD_VALUE2
496496
RESUME 3
497497
JUMP_BACKWARD_NO_INTERRUPT 4 (to 14)
498498
>> POP_TOP
@@ -526,7 +526,7 @@ async def _asyncwith(c):
526526
GET_AWAITABLE 2
527527
LOAD_CONST 0 (None)
528528
>> SEND 4 (to 92)
529-
YIELD_VALUE6
529+
YIELD_VALUE3
530530
RESUME 3
531531
JUMP_BACKWARD_NO_INTERRUPT 4 (to 82)
532532
>> CLEANUP_THROW
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Record the (virtual) exception block depth in the oparg of
2+
:opcode:`YIELD_VALUE`. Use this to avoid the expensive ``throw()`` when
3+
closing generators (and coroutines) that can be closed trivially.

‎Objects/genobject.c‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,15 +354,37 @@ gen_close(PyGenObject *gen, PyObject *args)
354354
PyObject*yf=_PyGen_yf(gen);
355355
interr=0;
356356

357+
if (gen->gi_frame_state==FRAME_CREATED) {
358+
gen->gi_frame_state=FRAME_COMPLETED;
359+
Py_RETURN_NONE;
360+
}
361+
if (gen->gi_frame_state >=FRAME_COMPLETED) {
362+
Py_RETURN_NONE;
363+
}
357364
if (yf) {
358365
PyFrameStatestate=gen->gi_frame_state;
359366
gen->gi_frame_state=FRAME_EXECUTING;
360367
err=gen_close_iter(yf);
361368
gen->gi_frame_state=state;
362369
Py_DECREF(yf);
363370
}
364-
if (err==0)
371+
_PyInterpreterFrame*frame= (_PyInterpreterFrame*)gen->gi_iframe;
372+
/* It is possible for the previous instruction to not be a
373+
* YIELD_VALUE if the debugger has changed the lineno. */
374+
if (err==0&&frame->prev_instr->opcode==YIELD_VALUE) {
375+
assert(frame->prev_instr[1].opcode==RESUME);
376+
intexception_handler_depth=frame->prev_instr->oparg;
377+
assert(exception_handler_depth>0);
378+
/* We can safely ignore the outermost try block
379+
* as it automatically generated to handle
380+
* StopIteration. */
381+
if (exception_handler_depth==1) {
382+
Py_RETURN_NONE;
383+
}
384+
}
385+
if (err==0) {
365386
PyErr_SetNone(PyExc_GeneratorExit);
387+
}
366388
retval=gen_send_ex(gen,Py_None,1,1);
367389
if (retval) {
368390
constchar*msg="generator ignored GeneratorExit";

‎Python/bytecodes.c‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,6 @@ dummy_func(
720720
// NOTE: It's important that YIELD_VALUE never raises an exception!
721721
// The compiler treats any exception raised here as a failed close()
722722
// or throw() call.
723-
assert(oparg==STACK_LEVEL());
724723
assert(frame!=&entry_frame);
725724
PyGenObject*gen=_PyFrame_GetGenerator(frame);
726725
gen->gi_frame_state=FRAME_SUSPENDED;

‎Python/compile.c‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7162,9 +7162,6 @@ stackdepth(basicblock *entryblock, int code_flags)
71627162
next=NULL;
71637163
break;
71647164
}
7165-
if (instr->i_opcode==YIELD_VALUE) {
7166-
instr->i_oparg=depth;
7167-
}
71687165
}
71697166
if (next!=NULL) {
71707167
assert(BB_HAS_FALLTHROUGH(b));
@@ -7332,6 +7329,9 @@ label_exception_targets(basicblock *entryblock) {
73327329
}
73337330
}
73347331
else {
7332+
if (instr->i_opcode==YIELD_VALUE) {
7333+
instr->i_oparg=except_stack->depth;
7334+
}
73357335
instr->i_except=handler;
73367336
}
73377337
}

‎Python/generated_cases.c.h‎

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎Python/opcode_metadata.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static const struct {
5959
[GET_ANEXT]= {1,2,DIR_NONE,DIR_NONE,DIR_NONE, true,INSTR_FMT_IX },
6060
[GET_AWAITABLE]= {1,1,DIR_NONE,DIR_NONE,DIR_NONE, true,INSTR_FMT_IB },
6161
[SEND]= {-1,-1,DIR_NONE,DIR_NONE,DIR_NONE, true,INSTR_FMT_IB },
62-
[YIELD_VALUE]= {1,1,DIR_NONE,DIR_NONE,DIR_NONE, true,INSTR_FMT_IB },
62+
[YIELD_VALUE]= {1,1,DIR_NONE,DIR_NONE,DIR_NONE, true,INSTR_FMT_IX },
6363
[POP_EXCEPT]= {1,0,DIR_NONE,DIR_NONE,DIR_NONE, true,INSTR_FMT_IX },
6464
[RERAISE]= {-1,-1,DIR_NONE,DIR_NONE,DIR_NONE, true,INSTR_FMT_IB },
6565
[PREP_RERAISE_STAR]= {2,1,DIR_NONE,DIR_NONE,DIR_NONE, true,INSTR_FMT_IX },

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp