@@ -2003,28 +2003,32 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
2003
2003
DEOPT_IF (!PyUnicode_CheckExact (left ), BINARY_OP );
2004
2004
DEOPT_IF (Py_TYPE (right ) != Py_TYPE (left ), BINARY_OP );
2005
2005
_Py_CODEUNIT true_next = next_instr [INLINE_CACHE_ENTRIES_BINARY_OP ];
2006
- int next_oparg = _Py_OPARG (true_next );
2007
2006
assert (_Py_OPCODE (true_next ) == STORE_FAST ||
2008
2007
_Py_OPCODE (true_next ) == STORE_FAST__LOAD_FAST );
2009
- /* In the common case, there are 2 references to the value
2010
- * stored in 'variable' when the v = v + ... is performed: one
2011
- * on the value stack (in 'v') and one still stored in the
2012
- * 'variable'. We try to delete the variable now to reduce
2013
- * the refcnt to 1.
2014
- */
2015
- PyObject * var = GETLOCAL (next_oparg );
2016
- DEOPT_IF (var != left , BINARY_OP );
2008
+ PyObject * * target_local = & GETLOCAL (_Py_OPARG (true_next ));
2009
+ DEOPT_IF (* target_local != left , BINARY_OP );
2017
2010
STAT_INC (BINARY_OP , hit );
2018
- GETLOCAL (next_oparg ) = NULL ;
2011
+ /* Handle `left = left + right` or `left += right` for str.
2012
+ *
2013
+ * When possible, extend `left` in place rather than
2014
+ * allocating a new PyUnicodeObject. This attempts to avoid
2015
+ * quadratic behavior when one neglects to use str.join().
2016
+ *
2017
+ * If `left` has only two references remaining (one from
2018
+ * the stack, one in the locals), DECREFing `left` leaves
2019
+ * only the locals reference, so PyUnicode_Append knows
2020
+ * that the string is safe to mutate.
2021
+ */
2019
2022
assert (Py_REFCNT (left ) >= 2 );
2020
2023
Py_DECREF (left ); // XXX never need to dealloc
2021
- STACK_SHRINK (1 );
2022
- PyUnicode_Append (& TOP () , right );
2024
+ STACK_SHRINK (2 );
2025
+ PyUnicode_Append (target_local , right );
2023
2026
Py_DECREF (right );
2024
- if (TOP () == NULL ) {
2027
+ if (* target_local == NULL ) {
2025
2028
goto error ;
2026
2029
}
2027
- JUMPBY (INLINE_CACHE_ENTRIES_BINARY_OP );
2030
+ // The STORE_FAST is already done.
2031
+ JUMPBY (INLINE_CACHE_ENTRIES_BINARY_OP + 1 );
2028
2032
NOTRACE_DISPATCH ();
2029
2033
}
2030
2034
0 commit comments