mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	GH-119258: Handle STORE_ATTR_WITH_HINT in tier two (GH-119481)
This commit is contained in:
		
							parent
							
								
									cfcc054dee
								
							
						
					
					
						commit
						5cd3ffd6b7
					
				
					 8 changed files with 137 additions and 61 deletions
				
			
		|  | @ -2119,11 +2119,8 @@ dummy_func( | |||
|             _GUARD_DORV_NO_DICT + | ||||
|             _STORE_ATTR_INSTANCE_VALUE; | ||||
| 
 | ||||
|         inst(STORE_ATTR_WITH_HINT, (unused/1, type_version/2, hint/1, value, owner --)) { | ||||
|             PyTypeObject *tp = Py_TYPE(owner); | ||||
|             assert(type_version != 0); | ||||
|             DEOPT_IF(tp->tp_version_tag != type_version); | ||||
|             assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); | ||||
|         op(_STORE_ATTR_WITH_HINT, (hint/1, value, owner --)) { | ||||
|             assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); | ||||
|             PyDictObject *dict = _PyObject_GetManagedDict(owner); | ||||
|             DEOPT_IF(dict == NULL); | ||||
|             assert(PyDict_CheckExact((PyObject *)dict)); | ||||
|  | @ -2158,6 +2155,11 @@ dummy_func( | |||
|             Py_DECREF(owner); | ||||
|         } | ||||
| 
 | ||||
|         macro(STORE_ATTR_WITH_HINT) = | ||||
|             unused/1 + | ||||
|             _GUARD_TYPE_VERSION + | ||||
|             _STORE_ATTR_WITH_HINT; | ||||
| 
 | ||||
|         op(_STORE_ATTR_SLOT, (index/1, value, owner --)) { | ||||
|             char *addr = (char *)owner + index; | ||||
|             STAT_INC(STORE_ATTR, hit); | ||||
|  |  | |||
							
								
								
									
										62
									
								
								Python/executor_cases.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										62
									
								
								Python/executor_cases.c.h
									
										
									
										generated
									
									
									
								
							|  | @ -2279,7 +2279,67 @@ | |||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         /* _STORE_ATTR_WITH_HINT is not a viable micro-op for tier 2 because it has unused cache entries */ | ||||
|         case _STORE_ATTR_WITH_HINT: { | ||||
|             PyObject *owner; | ||||
|             PyObject *value; | ||||
|             oparg = CURRENT_OPARG(); | ||||
|             owner = stack_pointer[-1]; | ||||
|             value = stack_pointer[-2]; | ||||
|             uint16_t hint = (uint16_t)CURRENT_OPERAND(); | ||||
|             assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); | ||||
|             PyDictObject *dict = _PyObject_GetManagedDict(owner); | ||||
|             if (dict == NULL) { | ||||
|                 UOP_STAT_INC(uopcode, miss); | ||||
|                 JUMP_TO_JUMP_TARGET(); | ||||
|             } | ||||
|             assert(PyDict_CheckExact((PyObject *)dict)); | ||||
|             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); | ||||
|             if (hint >= (size_t)dict->ma_keys->dk_nentries) { | ||||
|                 UOP_STAT_INC(uopcode, miss); | ||||
|                 JUMP_TO_JUMP_TARGET(); | ||||
|             } | ||||
|             PyObject *old_value; | ||||
|             uint64_t new_version; | ||||
|             if (DK_IS_UNICODE(dict->ma_keys)) { | ||||
|                 PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; | ||||
|                 if (ep->me_key != name) { | ||||
|                     UOP_STAT_INC(uopcode, miss); | ||||
|                     JUMP_TO_JUMP_TARGET(); | ||||
|                 } | ||||
|                 old_value = ep->me_value; | ||||
|                 if (old_value == NULL) { | ||||
|                     UOP_STAT_INC(uopcode, miss); | ||||
|                     JUMP_TO_JUMP_TARGET(); | ||||
|                 } | ||||
|                 new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value); | ||||
|                 ep->me_value = value; | ||||
|             } | ||||
|             else { | ||||
|                 PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint; | ||||
|                 if (ep->me_key != name) { | ||||
|                     UOP_STAT_INC(uopcode, miss); | ||||
|                     JUMP_TO_JUMP_TARGET(); | ||||
|                 } | ||||
|                 old_value = ep->me_value; | ||||
|                 if (old_value == NULL) { | ||||
|                     UOP_STAT_INC(uopcode, miss); | ||||
|                     JUMP_TO_JUMP_TARGET(); | ||||
|                 } | ||||
|                 new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value); | ||||
|                 ep->me_value = value; | ||||
|             } | ||||
|             Py_DECREF(old_value); | ||||
|             STAT_INC(STORE_ATTR, hit); | ||||
|             /* Ensure dict is GC tracked if it needs to be */ | ||||
|             if (!_PyObject_GC_IS_TRACKED(dict) && _PyObject_GC_MAY_BE_TRACKED(value)) { | ||||
|                 _PyObject_GC_TRACK(dict); | ||||
|             } | ||||
|             /* PEP 509 */ | ||||
|             dict->ma_version_tag = new_version; | ||||
|             Py_DECREF(owner); | ||||
|             stack_pointer += -2; | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case _STORE_ATTR_SLOT: { | ||||
|             PyObject *owner; | ||||
|  |  | |||
							
								
								
									
										80
									
								
								Python/generated_cases.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										80
									
								
								Python/generated_cases.c.h
									
										
									
										generated
									
									
									
								
							|  | @ -5578,46 +5578,52 @@ | |||
|             PyObject *owner; | ||||
|             PyObject *value; | ||||
|             /* Skip 1 cache entry */ | ||||
|             // _GUARD_TYPE_VERSION
 | ||||
|             owner = stack_pointer[-1]; | ||||
|             { | ||||
|                 uint32_t type_version = read_u32(&this_instr[2].cache); | ||||
|                 PyTypeObject *tp = Py_TYPE(owner); | ||||
|                 assert(type_version != 0); | ||||
|                 DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); | ||||
|             } | ||||
|             // _STORE_ATTR_WITH_HINT
 | ||||
|             value = stack_pointer[-2]; | ||||
|             uint32_t type_version = read_u32(&this_instr[2].cache); | ||||
|             uint16_t hint = read_u16(&this_instr[4].cache); | ||||
|             PyTypeObject *tp = Py_TYPE(owner); | ||||
|             assert(type_version != 0); | ||||
|             DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); | ||||
|             assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); | ||||
|             PyDictObject *dict = _PyObject_GetManagedDict(owner); | ||||
|             DEOPT_IF(dict == NULL, STORE_ATTR); | ||||
|             assert(PyDict_CheckExact((PyObject *)dict)); | ||||
|             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); | ||||
|             DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, STORE_ATTR); | ||||
|             PyObject *old_value; | ||||
|             uint64_t new_version; | ||||
|             if (DK_IS_UNICODE(dict->ma_keys)) { | ||||
|                 PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; | ||||
|                 DEOPT_IF(ep->me_key != name, STORE_ATTR); | ||||
|                 old_value = ep->me_value; | ||||
|                 DEOPT_IF(old_value == NULL, STORE_ATTR); | ||||
|                 new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value); | ||||
|                 ep->me_value = value; | ||||
|             { | ||||
|                 uint16_t hint = read_u16(&this_instr[4].cache); | ||||
|                 assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); | ||||
|                 PyDictObject *dict = _PyObject_GetManagedDict(owner); | ||||
|                 DEOPT_IF(dict == NULL, STORE_ATTR); | ||||
|                 assert(PyDict_CheckExact((PyObject *)dict)); | ||||
|                 PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); | ||||
|                 DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, STORE_ATTR); | ||||
|                 PyObject *old_value; | ||||
|                 uint64_t new_version; | ||||
|                 if (DK_IS_UNICODE(dict->ma_keys)) { | ||||
|                     PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; | ||||
|                     DEOPT_IF(ep->me_key != name, STORE_ATTR); | ||||
|                     old_value = ep->me_value; | ||||
|                     DEOPT_IF(old_value == NULL, STORE_ATTR); | ||||
|                     new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value); | ||||
|                     ep->me_value = value; | ||||
|                 } | ||||
|                 else { | ||||
|                     PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint; | ||||
|                     DEOPT_IF(ep->me_key != name, STORE_ATTR); | ||||
|                     old_value = ep->me_value; | ||||
|                     DEOPT_IF(old_value == NULL, STORE_ATTR); | ||||
|                     new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value); | ||||
|                     ep->me_value = value; | ||||
|                 } | ||||
|                 Py_DECREF(old_value); | ||||
|                 STAT_INC(STORE_ATTR, hit); | ||||
|                 /* Ensure dict is GC tracked if it needs to be */ | ||||
|                 if (!_PyObject_GC_IS_TRACKED(dict) && _PyObject_GC_MAY_BE_TRACKED(value)) { | ||||
|                     _PyObject_GC_TRACK(dict); | ||||
|                 } | ||||
|                 /* PEP 509 */ | ||||
|                 dict->ma_version_tag = new_version; | ||||
|                 Py_DECREF(owner); | ||||
|             } | ||||
|             else { | ||||
|                 PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint; | ||||
|                 DEOPT_IF(ep->me_key != name, STORE_ATTR); | ||||
|                 old_value = ep->me_value; | ||||
|                 DEOPT_IF(old_value == NULL, STORE_ATTR); | ||||
|                 new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value); | ||||
|                 ep->me_value = value; | ||||
|             } | ||||
|             Py_DECREF(old_value); | ||||
|             STAT_INC(STORE_ATTR, hit); | ||||
|             /* Ensure dict is GC tracked if it needs to be */ | ||||
|             if (!_PyObject_GC_IS_TRACKED(dict) && _PyObject_GC_MAY_BE_TRACKED(value)) { | ||||
|                 _PyObject_GC_TRACK(dict); | ||||
|             } | ||||
|             /* PEP 509 */ | ||||
|             dict->ma_version_tag = new_version; | ||||
|             Py_DECREF(owner); | ||||
|             stack_pointer += -2; | ||||
|             DISPATCH(); | ||||
|         } | ||||
|  |  | |||
							
								
								
									
										5
									
								
								Python/optimizer_cases.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								Python/optimizer_cases.c.h
									
										
									
										generated
									
									
									
								
							|  | @ -1079,7 +1079,10 @@ | |||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         /* _STORE_ATTR_WITH_HINT is not a viable micro-op for tier 2 */ | ||||
|         case _STORE_ATTR_WITH_HINT: { | ||||
|             stack_pointer += -2; | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case _STORE_ATTR_SLOT: { | ||||
|             stack_pointer += -2; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Brandt Bucher
						Brandt Bucher