mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	bpo-47053: Reduce deoptimization in BINARY_OP_INPLACE_ADD_UNICODE (GH-31318)
* Don't deopt if refcounts are too big * Detect more at specialization time
This commit is contained in:
		
							parent
							
								
									d7163bb35d
								
							
						
					
					
						commit
						cca43b7d64
					
				
					 4 changed files with 11 additions and 7 deletions
				
			
		|  | @ -2002,10 +2002,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int | |||
|             PyObject *right = TOP(); | ||||
|             DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); | ||||
|             DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP); | ||||
|             DEOPT_IF(Py_REFCNT(left) != 2, BINARY_OP); | ||||
|             _Py_CODEUNIT true_next = next_instr[INLINE_CACHE_ENTRIES_BINARY_OP]; | ||||
|             int next_oparg = _Py_OPARG(true_next); | ||||
|             assert(_Py_OPCODE(true_next) == STORE_FAST); | ||||
|             assert(_Py_OPCODE(true_next) == STORE_FAST || | ||||
|                    _Py_OPCODE(true_next) == STORE_FAST__LOAD_FAST); | ||||
|             /* In the common case, there are 2 references to the value
 | ||||
|             * stored in 'variable' when the v = v + ... is performed: one | ||||
|             * on the value stack (in 'v') and one still stored in the | ||||
|  | @ -2016,7 +2016,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int | |||
|             DEOPT_IF(var != left, BINARY_OP); | ||||
|             STAT_INC(BINARY_OP, hit); | ||||
|             GETLOCAL(next_oparg) = NULL; | ||||
|             Py_DECREF(left); | ||||
|             assert(Py_REFCNT(left) >= 2); | ||||
|             Py_DECREF(left); // XXX never need to dealloc
 | ||||
|             STACK_SHRINK(1); | ||||
|             PyUnicode_Append(&TOP(), right); | ||||
|             Py_DECREF(right); | ||||
|  | @ -5378,7 +5379,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int | |||
|                 PyObject *lhs = SECOND(); | ||||
|                 PyObject *rhs = TOP(); | ||||
|                 next_instr--; | ||||
|                 _Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg); | ||||
|                 _Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg, &GETLOCAL(0)); | ||||
|                 DISPATCH(); | ||||
|             } | ||||
|             else { | ||||
|  |  | |||
|  | @ -1742,7 +1742,7 @@ binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs) | |||
| 
 | ||||
| void | ||||
| _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, | ||||
|                         int oparg) | ||||
|                         int oparg, PyObject **locals) | ||||
| { | ||||
|     assert(_PyOpcode_Caches[BINARY_OP] == INLINE_CACHE_ENTRIES_BINARY_OP); | ||||
|     _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(instr + 1); | ||||
|  | @ -1754,7 +1754,9 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, | |||
|             } | ||||
|             if (PyUnicode_CheckExact(lhs)) { | ||||
|                 _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_BINARY_OP + 1]; | ||||
|                 if (_Py_OPCODE(next) == STORE_FAST && Py_REFCNT(lhs) == 2) { | ||||
|                 bool to_store = (_Py_OPCODE(next) == STORE_FAST || | ||||
|                                  _Py_OPCODE(next) == STORE_FAST__LOAD_FAST); | ||||
|                 if (to_store && locals[_Py_OPARG(next)] == lhs) { | ||||
|                     _Py_SET_OPCODE(*instr, BINARY_OP_INPLACE_ADD_UNICODE); | ||||
|                     goto success; | ||||
|                 } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dennis Sweeney
						Dennis Sweeney