@@ -588,7 +588,7 @@ dummy_func(
588588 BINARY_OP_SUBSCR_STR_INT ,
589589 BINARY_OP_SUBSCR_DICT ,
590590 BINARY_OP_SUBSCR_GETITEM ,
591- // BINARY_OP_INPLACE_ADD_UNICODE, // See comments at that opcode.
591+ BINARY_OP_INPLACE_ADD_UNICODE ,
592592 BINARY_OP_EXTEND ,
593593 };
594594
@@ -762,13 +762,10 @@ dummy_func(
762762 macro (BINARY_OP_ADD_UNICODE ) =
763763 _GUARD_TOS_UNICODE + _GUARD_NOS_UNICODE + unused /5 + _BINARY_OP_ADD_UNICODE + _POP_TOP_UNICODE + _POP_TOP_UNICODE ;
764764
765- // This is a subtle one. It's a super-instruction for
766- // BINARY_OP_ADD_UNICODE followed by STORE_FAST
767- // where the store goes into the left argument.
768- // So the inputs are the same as for all BINARY_OP
769- // specializations, but there is no output.
770- // At the end we just skip over the STORE_FAST.
771- op (_BINARY_OP_INPLACE_ADD_UNICODE , (left , right -- )) {
765+ // This is a subtle one. We write NULL to the local
766+ // of the following STORE_FAST and leave the result for STORE_FAST
767+ // later to store.
768+ op (_BINARY_OP_INPLACE_ADD_UNICODE , (left , right -- res )) {
772769 PyObject * left_o = PyStackRef_AsPyObjectBorrow (left );
773770 assert (PyUnicode_CheckExact (left_o ));
774771 assert (PyUnicode_CheckExact (PyStackRef_AsPyObjectBorrow (right )));
@@ -796,20 +793,16 @@ dummy_func(
796793 * that the string is safe to mutate.
797794 */
798795 assert (Py_REFCNT (left_o ) >= 2 || !PyStackRef_IsHeapSafe (left ));
799- PyStackRef_CLOSE_SPECIALIZED (left , _PyUnicode_ExactDealloc );
800- DEAD (left );
801796 PyObject * temp = PyStackRef_AsPyObjectSteal (* target_local );
802- PyObject * right_o = PyStackRef_AsPyObjectSteal (right );
797+ PyObject * right_o = PyStackRef_AsPyObjectBorrow (right );
803798 PyUnicode_Append (& temp , right_o );
804- * target_local = PyStackRef_FromPyObjectSteal (temp );
805- Py_DECREF (right_o );
806- ERROR_IF (PyStackRef_IsNull (* target_local ));
807- #if TIER_ONE
808- // The STORE_FAST is already done. This is done here in tier one,
809- // and during trace projection in tier two:
810- assert (next_instr -> op .code == STORE_FAST );
811- SKIP_OVER (1 );
812- #endif
799+ PyStackRef_CLOSE_SPECIALIZED (right , _PyUnicode_ExactDealloc );
800+ DEAD (right );
801+ PyStackRef_CLOSE_SPECIALIZED (left , _PyUnicode_ExactDealloc );
802+ DEAD (left );
803+ ERROR_IF (temp == NULL );
804+ res = PyStackRef_FromPyObjectSteal (temp );
805+ * target_local = PyStackRef_NULL ;
813806 }
814807
815808 op (_GUARD_BINARY_OP_EXTEND , (descr /4 , left , right -- left , right )) {
@@ -4330,8 +4323,7 @@ dummy_func(
43304323 DEOPT_IF (callable_o != interp -> callable_cache .list_append );
43314324 }
43324325
4333- // This is secretly a super-instruction
4334- op (_CALL_LIST_APPEND , (callable , self , arg -- c , s )) {
4326+ op (_CALL_LIST_APPEND , (callable , self , arg -- none , c , s )) {
43354327 assert (oparg == 1 );
43364328 PyObject * self_o = PyStackRef_AsPyObjectBorrow (self );
43374329
@@ -4344,13 +4336,9 @@ dummy_func(
43444336 }
43454337 c = callable ;
43464338 s = self ;
4347- INPUTS_DEAD ();
4348- #if TIER_ONE
4349- // Skip the following POP_TOP. This is done here in tier one, and
4350- // during trace projection in tier two:
4351- assert (next_instr -> op .code == POP_TOP );
4352- SKIP_OVER (1 );
4353- #endif
4339+ DEAD (callable );
4340+ DEAD (self );
4341+ none = PyStackRef_None ;
43544342 }
43554343
43564344 op (_CALL_METHOD_DESCRIPTOR_O , (callable , self_or_null , args [oparg ] -- res )) {
@@ -5598,15 +5586,9 @@ dummy_func(
55985586 // Super instructions. Instruction deopted. There's a mismatch in what the stack expects
55995587 // in the optimizer. So we have to reflect in the trace correctly.
56005588 _PyThreadStateImpl * _tstate = (_PyThreadStateImpl * )tstate ;
5601- if ((_tstate -> jit_tracer_state .prev_state .instr -> op .code == CALL_LIST_APPEND &&
5602- opcode == POP_TOP ) ||
5603- (_tstate -> jit_tracer_state .prev_state .instr -> op .code == BINARY_OP_INPLACE_ADD_UNICODE &&
5604- opcode == STORE_FAST )) {
5605- _tstate -> jit_tracer_state .prev_state .instr_is_super = true;
5606- }
5607- else {
5608- _tstate -> jit_tracer_state .prev_state .instr = next_instr ;
5609- }
5589+ // JIT should have disabled super instructions, as we can
5590+ // do these optimizations ourselves in the JIT.
5591+ _tstate -> jit_tracer_state .prev_state .instr = next_instr ;
56105592 PyObject * prev_code = PyStackRef_AsPyObjectBorrow (frame -> f_executable );
56115593 if (_tstate -> jit_tracer_state .prev_state .instr_code != (PyCodeObject * )prev_code ) {
56125594 Py_SETREF (_tstate -> jit_tracer_state .prev_state .instr_code , (PyCodeObject * )Py_NewRef ((prev_code )));
0 commit comments