@@ -2568,22 +2568,42 @@ compiler_check_debug_args(struct compiler *c, arguments_ty args)
2568
2568
return 1 ;
2569
2569
}
2570
2570
2571
+ static inline int
2572
+ insert_instruction (basicblock * block , int pos , struct instr * instr ) {
2573
+ if (basicblock_next_instr (block ) < 0 ) {
2574
+ return -1 ;
2575
+ }
2576
+ for (int i = block -> b_iused - 1 ; i > pos ; i -- ) {
2577
+ block -> b_instr [i ] = block -> b_instr [i - 1 ];
2578
+ }
2579
+ block -> b_instr [pos ] = * instr ;
2580
+ return 0 ;
2581
+ }
2582
+
2571
2583
static int
2572
- coroutine_stopiteration_handler (struct compiler * c , jump_target_label * handler )
2584
+ wrap_in_stopiteration_handler (struct compiler * c )
2573
2585
{
2574
- ADDOP_LOAD_CONST (c , NO_LOCATION , Py_None );
2575
- ADDOP (c , NO_LOCATION , RETURN_VALUE );
2576
- if (cfg_builder_use_label (CFG_BUILDER (c ), * handler ) < 0 ) {
2577
- return 0 ;
2578
- }
2579
- jump_target_label other = cfg_new_label (CFG_BUILDER (c ));
2580
- if (!IS_LABEL (other )) {
2586
+ NEW_JUMP_TARGET_LABEL (c , handler );
2587
+ NEW_JUMP_TARGET_LABEL (c , next );
2588
+
2589
+ /* Insert SETUP_CLEANUP at start */
2590
+ struct instr setup = {
2591
+ .i_opcode = SETUP_CLEANUP ,
2592
+ .i_oparg = handler .id ,
2593
+ .i_loc = NO_LOCATION ,
2594
+ .i_target = NULL ,
2595
+ };
2596
+ if (insert_instruction (c -> u -> u_cfg_builder .g_entryblock , 0 , & setup )) {
2581
2597
return 0 ;
2582
2598
}
2583
- USE_LABEL (c , * handler );
2599
+
2600
+ ADDOP_LOAD_CONST (c , NO_LOCATION , Py_None );
2601
+ ADDOP (c , NO_LOCATION , RETURN_VALUE );
2602
+ USE_LABEL (c , handler );
2584
2603
ADDOP_I (c , NO_LOCATION , LOAD_ERROR , 1 ); // StopIteration
2585
2604
ADDOP (c , NO_LOCATION , CHECK_EXC_MATCH );
2586
- ADDOP_JUMP (c , NO_LOCATION , POP_JUMP_IF_FALSE , other );
2605
+ ADDOP_JUMP (c , NO_LOCATION , POP_JUMP_IF_FALSE , next );
2606
+ ADDOP (c , NO_LOCATION , PUSH_EXC_INFO );
2587
2607
ADDOP_I (c , NO_LOCATION , LOAD_ERROR , 2 ); // RuntimeError
2588
2608
const char * msg = c -> u -> u_ste -> ste_coroutine ?
2589
2609
(c -> u -> u_ste -> ste_generator ?
@@ -2597,9 +2617,31 @@ coroutine_stopiteration_handler(struct compiler *c, jump_target_label *handler)
2597
2617
}
2598
2618
ADDOP_LOAD_CONST_NEW (c , NO_LOCATION , message );
2599
2619
ADDOP_I (c , NO_LOCATION , CALL , 0 );
2620
+ ADDOP_I (c , NO_LOCATION , SWAP , 2 );
2600
2621
ADDOP_I (c , NO_LOCATION , RAISE_VARARGS , 2 );
2601
2622
2602
- USE_LABEL (c , other );
2623
+ USE_LABEL (c , next );
2624
+ if (c -> u -> u_ste -> ste_coroutine &&
2625
+ c -> u -> u_ste -> ste_generator )
2626
+ {
2627
+ NEW_JUMP_TARGET_LABEL (c , next );
2628
+ ADDOP_I (c , NO_LOCATION , LOAD_ERROR , 3 ); // StopAsyncIteration
2629
+ ADDOP (c , NO_LOCATION , CHECK_EXC_MATCH );
2630
+ ADDOP_JUMP (c , NO_LOCATION , POP_JUMP_IF_FALSE , next );
2631
+ ADDOP (c , NO_LOCATION , PUSH_EXC_INFO );
2632
+ ADDOP_I (c , NO_LOCATION , LOAD_ERROR , 2 ); // RuntimeError
2633
+ const char * msg = "async generator raised StopAsyncIteration" ;
2634
+ PyObject * message = _PyUnicode_FromASCII (msg , strlen (msg ));
2635
+ if (message == NULL ) {
2636
+ return 0 ;
2637
+ }
2638
+ ADDOP_LOAD_CONST_NEW (c , NO_LOCATION , message );
2639
+ ADDOP_I (c , NO_LOCATION , CALL , 0 );
2640
+ ADDOP_I (c , NO_LOCATION , SWAP , 2 );
2641
+ ADDOP_I (c , NO_LOCATION , RAISE_VARARGS , 2 );
2642
+
2643
+ USE_LABEL (c , next );
2644
+ }
2603
2645
ADDOP_I (c , NO_LOCATION , RERAISE , 1 );
2604
2646
return 1 ;
2605
2647
}
@@ -2669,17 +2711,6 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
2669
2711
return 0 ;
2670
2712
}
2671
2713
2672
- bool is_coro = (c -> u -> u_ste -> ste_coroutine || c -> u -> u_ste -> ste_generator );
2673
- jump_target_label handler ;
2674
- if (is_coro ) {
2675
- handler = cfg_new_label (CFG_BUILDER (c ));
2676
- if (!IS_LABEL (handler )) {
2677
- compiler_exit_scope (c );
2678
- return 0 ;
2679
- }
2680
- ADDOP_JUMP (c , NO_LOCATION , SETUP_CLEANUP , handler );
2681
- }
2682
-
2683
2714
/* if not -OO mode, add docstring */
2684
2715
if (c -> c_optimize < 2 ) {
2685
2716
docstring = _PyAST_GetDocString (body );
@@ -2695,8 +2726,8 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
2695
2726
for (i = docstring ? 1 : 0 ; i < asdl_seq_LEN (body ); i ++ ) {
2696
2727
VISIT_IN_SCOPE (c , stmt , (stmt_ty )asdl_seq_GET (body , i ));
2697
2728
}
2698
- if (is_coro ) {
2699
- if (!coroutine_stopiteration_handler ( c , & handler )) {
2729
+ if (c -> u -> u_ste -> ste_coroutine || c -> u -> u_ste -> ste_generator ) {
2730
+ if (!wrap_in_stopiteration_handler ( c )) {
2700
2731
compiler_exit_scope (c );
2701
2732
return 0 ;
2702
2733
}
@@ -5542,6 +5573,9 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
5542
5573
if (type != COMP_GENEXP ) {
5543
5574
ADDOP (c , LOC (e ), RETURN_VALUE );
5544
5575
}
5576
+ if (!wrap_in_stopiteration_handler (c )) {
5577
+ goto error_in_scope ;
5578
+ }
5545
5579
5546
5580
co = assemble (c , 1 );
5547
5581
qualname = c -> u -> u_qualname ;
@@ -8606,18 +8640,6 @@ build_cellfixedoffsets(struct compiler *c)
8606
8640
return fixed ;
8607
8641
}
8608
8642
8609
- static inline int
8610
- insert_instruction (basicblock * block , int pos , struct instr * instr ) {
8611
- if (basicblock_next_instr (block ) < 0 ) {
8612
- return -1 ;
8613
- }
8614
- for (int i = block -> b_iused - 1 ; i > pos ; i -- ) {
8615
- block -> b_instr [i ] = block -> b_instr [i - 1 ];
8616
- }
8617
- block -> b_instr [pos ] = * instr ;
8618
- return 0 ;
8619
- }
8620
-
8621
8643
static int
8622
8644
insert_prefix_instructions (struct compiler * c , basicblock * entryblock ,
8623
8645
int * fixed , int nfreevars , int code_flags )
0 commit comments