@@ -2568,22 +2568,42 @@ compiler_check_debug_args(struct compiler *c, arguments_ty args)
25682568 return 1 ;
25692569}
25702570
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+
25712583static int
2572- coroutine_stopiteration_handler (struct compiler * c , jump_target_label * handler )
2584+ wrap_in_stopiteration_handler (struct compiler * c )
25732585{
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 )) {
25812597 return 0 ;
25822598 }
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 );
25842603 ADDOP_I (c , NO_LOCATION , LOAD_ERROR , 1 ); // StopIteration
25852604 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 );
25872607 ADDOP_I (c , NO_LOCATION , LOAD_ERROR , 2 ); // RuntimeError
25882608 const char * msg = c -> u -> u_ste -> ste_coroutine ?
25892609 (c -> u -> u_ste -> ste_generator ?
@@ -2597,9 +2617,31 @@ coroutine_stopiteration_handler(struct compiler *c, jump_target_label *handler)
25972617 }
25982618 ADDOP_LOAD_CONST_NEW (c , NO_LOCATION , message );
25992619 ADDOP_I (c , NO_LOCATION , CALL , 0 );
2620+ ADDOP_I (c , NO_LOCATION , SWAP , 2 );
26002621 ADDOP_I (c , NO_LOCATION , RAISE_VARARGS , 2 );
26012622
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+ }
26032645 ADDOP_I (c , NO_LOCATION , RERAISE , 1 );
26042646 return 1 ;
26052647}
@@ -2669,17 +2711,6 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
26692711 return 0 ;
26702712 }
26712713
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-
26832714 /* if not -OO mode, add docstring */
26842715 if (c -> c_optimize < 2 ) {
26852716 docstring = _PyAST_GetDocString (body );
@@ -2695,8 +2726,8 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
26952726 for (i = docstring ? 1 : 0 ; i < asdl_seq_LEN (body ); i ++ ) {
26962727 VISIT_IN_SCOPE (c , stmt , (stmt_ty )asdl_seq_GET (body , i ));
26972728 }
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 )) {
27002731 compiler_exit_scope (c );
27012732 return 0 ;
27022733 }
@@ -5542,6 +5573,9 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
55425573 if (type != COMP_GENEXP ) {
55435574 ADDOP (c , LOC (e ), RETURN_VALUE );
55445575 }
5576+ if (!wrap_in_stopiteration_handler (c )) {
5577+ goto error_in_scope ;
5578+ }
55455579
55465580 co = assemble (c , 1 );
55475581 qualname = c -> u -> u_qualname ;
@@ -8606,18 +8640,6 @@ build_cellfixedoffsets(struct compiler *c)
86068640 return fixed ;
86078641}
86088642
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-
86218643static int
86228644insert_prefix_instructions (struct compiler * c , basicblock * entryblock ,
86238645 int * fixed , int nfreevars , int code_flags )
0 commit comments