mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	gh-104909: Split some more insts into ops (#109943)
These are the most popular specializations of `LOAD_ATTR` and `STORE_ATTR` that weren't already viable uops: * Split LOAD_ATTR_METHOD_WITH_VALUES * Split LOAD_ATTR_METHOD_NO_DICT * Split LOAD_ATTR_SLOT * Split STORE_ATTR_SLOT * Split STORE_ATTR_INSTANCE_VALUE Also: * Add `-v` flag to code generator which prints a list of non-viable uops (easter-egg: it can print execution counts -- see source) * Double _Py_UOP_MAX_TRACE_LENGTH to 128 I had dropped one of the DEOPT_IF() calls! :-(
This commit is contained in:
		
							parent
							
								
									45cf5b0c69
								
							
						
					
					
						commit
						5bb6f0fcba
					
				
					 8 changed files with 519 additions and 115 deletions
				
			
		
							
								
								
									
										139
									
								
								Python/executor_cases.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										139
									
								
								Python/executor_cases.c.h
									
										
									
										generated
									
									
									
								
							|  | @ -1714,6 +1714,83 @@ | |||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case _LOAD_ATTR_SLOT: { | ||||
|             PyObject *owner; | ||||
|             PyObject *attr; | ||||
|             PyObject *null = NULL; | ||||
|             owner = stack_pointer[-1]; | ||||
|             uint16_t index = (uint16_t)operand; | ||||
|             char *addr = (char *)owner + index; | ||||
|             attr = *(PyObject **)addr; | ||||
|             DEOPT_IF(attr == NULL, LOAD_ATTR); | ||||
|             STAT_INC(LOAD_ATTR, hit); | ||||
|             Py_INCREF(attr); | ||||
|             null = NULL; | ||||
|             Py_DECREF(owner); | ||||
|             STACK_GROW(((oparg & 1) ? 1 : 0)); | ||||
|             stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr; | ||||
|             if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; } | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case _GUARD_DORV_VALUES: { | ||||
|             PyObject *owner; | ||||
|             owner = stack_pointer[-1]; | ||||
|             PyTypeObject *tp = Py_TYPE(owner); | ||||
|             assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); | ||||
|             PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); | ||||
|             DEOPT_IF(!_PyDictOrValues_IsValues(dorv), STORE_ATTR); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case _STORE_ATTR_INSTANCE_VALUE: { | ||||
|             PyObject *owner; | ||||
|             PyObject *value; | ||||
|             owner = stack_pointer[-1]; | ||||
|             value = stack_pointer[-2]; | ||||
|             uint16_t index = (uint16_t)operand; | ||||
|             PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); | ||||
|             STAT_INC(STORE_ATTR, hit); | ||||
|             PyDictValues *values = _PyDictOrValues_GetValues(dorv); | ||||
|             PyObject *old_value = values->values[index]; | ||||
|             values->values[index] = value; | ||||
|             if (old_value == NULL) { | ||||
|                 _PyDictValues_AddToInsertionOrder(values, index); | ||||
|             } | ||||
|             else { | ||||
|                 Py_DECREF(old_value); | ||||
|             } | ||||
|             Py_DECREF(owner); | ||||
|             STACK_SHRINK(2); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case _GUARD_TYPE_VERSION_STORE: { | ||||
|             PyObject *owner; | ||||
|             owner = stack_pointer[-1]; | ||||
|             uint32_t type_version = (uint32_t)operand; | ||||
|             PyTypeObject *tp = Py_TYPE(owner); | ||||
|             assert(type_version != 0); | ||||
|             DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case _STORE_ATTR_SLOT: { | ||||
|             PyObject *owner; | ||||
|             PyObject *value; | ||||
|             owner = stack_pointer[-1]; | ||||
|             value = stack_pointer[-2]; | ||||
|             uint16_t index = (uint16_t)operand; | ||||
|             char *addr = (char *)owner + index; | ||||
|             STAT_INC(STORE_ATTR, hit); | ||||
|             PyObject *old_value = *(PyObject **)addr; | ||||
|             *(PyObject **)addr = value; | ||||
|             Py_XDECREF(old_value); | ||||
|             Py_DECREF(owner); | ||||
|             STACK_SHRINK(2); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case COMPARE_OP: { | ||||
|             PyObject *right; | ||||
|             PyObject *left; | ||||
|  | @ -2219,6 +2296,68 @@ | |||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT: { | ||||
|             PyObject *owner; | ||||
|             owner = stack_pointer[-1]; | ||||
|             PyTypeObject *owner_cls = Py_TYPE(owner); | ||||
|             assert(owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT); | ||||
|             PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner); | ||||
|             DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && | ||||
|                      !_PyObject_MakeInstanceAttributesFromDict(owner, dorv), | ||||
|                      LOAD_ATTR); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case _GUARD_KEYS_VERSION: { | ||||
|             PyObject *owner; | ||||
|             owner = stack_pointer[-1]; | ||||
|             uint32_t keys_version = (uint32_t)operand; | ||||
|             PyTypeObject *owner_cls = Py_TYPE(owner); | ||||
|             PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; | ||||
|             DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version != | ||||
|                      keys_version, LOAD_ATTR); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case _LOAD_ATTR_METHOD_WITH_VALUES: { | ||||
|             PyObject *owner; | ||||
|             PyObject *attr; | ||||
|             PyObject *self; | ||||
|             owner = stack_pointer[-1]; | ||||
|             PyObject *descr = (PyObject *)operand; | ||||
|             assert(oparg & 1); | ||||
|             /* Cached method object */ | ||||
|             STAT_INC(LOAD_ATTR, hit); | ||||
|             assert(descr != NULL); | ||||
|             attr = Py_NewRef(descr); | ||||
|             assert(_PyType_HasFeature(Py_TYPE(attr), Py_TPFLAGS_METHOD_DESCRIPTOR)); | ||||
|             self = owner; | ||||
|             STACK_GROW(1); | ||||
|             stack_pointer[-2] = attr; | ||||
|             stack_pointer[-1] = self; | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case _LOAD_ATTR_METHOD_NO_DICT: { | ||||
|             PyObject *owner; | ||||
|             PyObject *attr; | ||||
|             PyObject *self; | ||||
|             owner = stack_pointer[-1]; | ||||
|             PyObject *descr = (PyObject *)operand; | ||||
|             assert(oparg & 1); | ||||
|             PyTypeObject *owner_cls = Py_TYPE(owner); | ||||
|             assert(owner_cls->tp_dictoffset == 0); | ||||
|             STAT_INC(LOAD_ATTR, hit); | ||||
|             assert(descr != NULL); | ||||
|             assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); | ||||
|             attr = Py_NewRef(descr); | ||||
|             self = owner; | ||||
|             STACK_GROW(1); | ||||
|             stack_pointer[-2] = attr; | ||||
|             stack_pointer[-1] = self; | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: { | ||||
|             PyObject *null; | ||||
|             PyObject *callable; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Guido van Rossum
						Guido van Rossum