@@ -587,25 +587,32 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
587587 assert (0 );
588588 }
589589 } else if (mp_obj_is_exception_type (TOP ())) {
590- mp_obj_t args [3 ] = {sp [0 ], sp [-1 ], sp [-2 ]};
591- mp_obj_t ret_value = mp_call_function_n_kw (sp [-3 ], 3 , 0 , args );
592- // Pop __exit__ boundmethod at sp[-3]
593- // TODO: Once semantics is proven, optimize for case when ret_value == True
594- sp [-3 ] = sp [-2 ];
595- sp [-2 ] = sp [-1 ];
596- sp [-1 ] = sp [0 ];
597- sp -- ;
590+ // Need to pass (sp[0], sp[-1], sp[-2]) as arguments so must reverse the
591+ // order of these on the value stack (don't want to create a temporary
592+ // array because it increases stack footprint of the VM).
593+ mp_obj_t obj = sp [-2 ];
594+ sp [-2 ] = sp [0 ];
595+ sp [0 ] = obj ;
596+ mp_obj_t ret_value = mp_call_function_n_kw (sp [-3 ], 3 , 0 , & sp [-2 ]);
598597 if (mp_obj_is_true (ret_value )) {
599598 // This is what CPython does
600599 //PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_SILENCED));
601600 // But what we need to do is - pop exception from value stack...
602- sp -= 3 ;
601+ sp -= 4 ;
603602 // ... pop "with" exception handler, and signal END_FINALLY
604603 // to just execute finally handler normally (by pushing None
605604 // on value stack)
606605 assert (exc_sp >= exc_stack );
607606 POP_EXC_BLOCK ();
608607 PUSH (mp_const_none );
608+ } else {
609+ // Pop __exit__ boundmethod at sp[-3], remembering that top 3 values
610+ // are reversed.
611+ sp [-3 ] = sp [0 ];
612+ obj = sp [-2 ];
613+ sp [-2 ] = sp [-1 ];
614+ sp [-1 ] = obj ;
615+ sp -- ;
609616 }
610617 } else {
611618 assert (0 );
0 commit comments