@@ -488,17 +488,9 @@ optimize_uops(
488488 _PyUOpInstruction * this_instr = NULL ;
489489 JitOptRef * stack_pointer = ctx -> frame -> stack_pointer ;
490490
491- for (int i = 0 ; i < trace_len ; i ++ ) {
491+ int i = 0 ;
492+ for (; i < trace_len && !ctx -> done ; i ++ ) {
492493 this_instr = & trace [i ];
493- if (ctx -> done ) {
494- // Don't do any more optimization, but
495- // we still need to reach a terminator for corrctness.
496- * (ctx -> out_buffer .next ++ ) = * this_instr ;
497- if (is_terminator_uop (this_instr )) {
498- break ;
499- }
500- continue ;
501- }
502494
503495 int oparg = this_instr -> oparg ;
504496 opcode = this_instr -> opcode ;
@@ -531,10 +523,6 @@ optimize_uops(
531523 assert (STACK_LEVEL () >= 0 );
532524 }
533525 }
534- if (ctx -> out_of_space ) {
535- DPRINTF (3 , "\n" );
536- DPRINTF (1 , "Out of space in abstract interpreter\n" );
537- }
538526 if (ctx -> contradiction ) {
539527 // Attempted to push a "bottom" (contradiction) symbol onto the stack.
540528 // This means that the abstract interpreter has optimized to trace
@@ -548,6 +536,35 @@ optimize_uops(
548536 OPT_STAT_INC (optimizer_contradiction );
549537 return 0 ;
550538 }
539+ if (ctx -> out_of_space ) {
540+ DPRINTF (3 , "\n" );
541+ DPRINTF (1 , "Out of space in abstract interpreter at length %d\n" ,
542+ uop_buffer_length (& ctx -> out_buffer ));
543+ // Rewind to previous instruction and replace with _EXIT_TRACE.
544+ _PyUOpInstruction * curr = uop_buffer_last (& ctx -> out_buffer );
545+ while (curr -> opcode != _SET_IP ) {
546+ if (!uop_buffer_rewind (& ctx -> out_buffer )) {
547+ // Reached the start.
548+ return 0 ;
549+ }
550+ curr = uop_buffer_last (& ctx -> out_buffer );
551+ }
552+ assert (curr -> opcode == _SET_IP );
553+ int32_t old_target = (int32_t )uop_get_target (curr );
554+ curr -> opcode = _EXIT_TRACE ;
555+ curr -> format = UOP_FORMAT_TARGET ;
556+ curr -> target = old_target ;
557+ DPRINTF (1 , "Rewound to length %d\n" , uop_buffer_length (& ctx -> out_buffer ));
558+ }
559+ else {
560+ // Don't do any more optimization, but
561+ // we still need to reach a terminator for correctness.
562+ while (!is_terminator_uop (uop_buffer_last (& ctx -> out_buffer ))) {
563+ this_instr = & trace [i ];
564+ * (ctx -> out_buffer .next ++ ) = * this_instr ;
565+ i ++ ;
566+ }
567+ }
551568
552569 /* Either reached the end or cannot optimize further, but there
553570 * would be no benefit in retrying later */
0 commit comments