mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	bpo-46841: Move the cache for LOAD_GLOBAL inline. (GH-31575)
				
					
				
			This commit is contained in:
		
							parent
							
								
									da7d99a4de
								
							
						
					
					
						commit
						4558af5a8f
					
				
					 10 changed files with 284 additions and 232 deletions
				
			
		|  | @ -2993,25 +2993,26 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int | |||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             /* Skip over inline cache */ | ||||
|             JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL); | ||||
|             PUSH(v); | ||||
|             DISPATCH(); | ||||
|         } | ||||
| 
 | ||||
|         TARGET(LOAD_GLOBAL_ADAPTIVE) { | ||||
|             assert(cframe.use_tracing == 0); | ||||
|             SpecializedCacheEntry *cache = GET_CACHE(); | ||||
|             if (cache->adaptive.counter == 0) { | ||||
|                 PyObject *name = GETITEM(names, cache->adaptive.original_oparg); | ||||
|             uint16_t counter = *next_instr; | ||||
|             if (counter == 0) { | ||||
|                 PyObject *name = GETITEM(names, oparg); | ||||
|                 next_instr--; | ||||
|                 if (_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name, cache) < 0) { | ||||
|                 if (_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name) < 0) { | ||||
|                     goto error; | ||||
|                 } | ||||
|                 DISPATCH(); | ||||
|             } | ||||
|             else { | ||||
|                 STAT_INC(LOAD_GLOBAL, deferred); | ||||
|                 cache->adaptive.counter--; | ||||
|                 oparg = cache->adaptive.original_oparg; | ||||
|                 *next_instr = counter-1; | ||||
|                 JUMP_TO_INSTRUCTION(LOAD_GLOBAL); | ||||
|             } | ||||
|         } | ||||
|  | @ -3020,13 +3021,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int | |||
|             assert(cframe.use_tracing == 0); | ||||
|             DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL); | ||||
|             PyDictObject *dict = (PyDictObject *)GLOBALS(); | ||||
|             SpecializedCacheEntry *caches = GET_CACHE(); | ||||
|             _PyAdaptiveEntry *cache0 = &caches[0].adaptive; | ||||
|             _PyLoadGlobalCache *cache1 = &caches[-1].load_global; | ||||
|             DEOPT_IF(dict->ma_keys->dk_version != cache1->module_keys_version, LOAD_GLOBAL); | ||||
|             PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + cache0->index; | ||||
|             _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; | ||||
|             uint32_t version = read32(&cache->module_keys_version); | ||||
|             DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); | ||||
|             PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + cache->index; | ||||
|             PyObject *res = ep->me_value; | ||||
|             DEOPT_IF(res == NULL, LOAD_GLOBAL); | ||||
|             JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL); | ||||
|             STAT_INC(LOAD_GLOBAL, hit); | ||||
|             Py_INCREF(res); | ||||
|             PUSH(res); | ||||
|  | @ -3039,14 +3040,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int | |||
|             DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL); | ||||
|             PyDictObject *mdict = (PyDictObject *)GLOBALS(); | ||||
|             PyDictObject *bdict = (PyDictObject *)BUILTINS(); | ||||
|             SpecializedCacheEntry *caches = GET_CACHE(); | ||||
|             _PyAdaptiveEntry *cache0 = &caches[0].adaptive; | ||||
|             _PyLoadGlobalCache *cache1 = &caches[-1].load_global; | ||||
|             DEOPT_IF(mdict->ma_keys->dk_version != cache1->module_keys_version, LOAD_GLOBAL); | ||||
|             DEOPT_IF(bdict->ma_keys->dk_version != cache1->builtin_keys_version, LOAD_GLOBAL); | ||||
|             PyDictKeyEntry *ep = DK_ENTRIES(bdict->ma_keys) + cache0->index; | ||||
|             _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; | ||||
|             uint32_t mod_version = read32(&cache->module_keys_version); | ||||
|             uint16_t bltn_version = cache->builtin_keys_version; | ||||
|             DEOPT_IF(mdict->ma_keys->dk_version != mod_version, LOAD_GLOBAL); | ||||
|             DEOPT_IF(bdict->ma_keys->dk_version != bltn_version, LOAD_GLOBAL); | ||||
|             PyDictKeyEntry *ep = DK_ENTRIES(bdict->ma_keys) + cache->index; | ||||
|             PyObject *res = ep->me_value; | ||||
|             DEOPT_IF(res == NULL, LOAD_GLOBAL); | ||||
|             JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL); | ||||
|             STAT_INC(LOAD_GLOBAL, hit); | ||||
|             Py_INCREF(res); | ||||
|             PUSH(res); | ||||
|  | @ -5594,7 +5596,7 @@ opname ## _miss: \ | |||
| 
 | ||||
| MISS_WITH_CACHE(LOAD_ATTR) | ||||
| MISS_WITH_CACHE(STORE_ATTR) | ||||
| MISS_WITH_CACHE(LOAD_GLOBAL) | ||||
| MISS_WITH_INLINE_CACHE(LOAD_GLOBAL) | ||||
| MISS_WITH_CACHE(LOAD_METHOD) | ||||
| MISS_WITH_CACHE(PRECALL) | ||||
| MISS_WITH_CACHE(CALL) | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ | |||
| #include "pycore_long.h"          // _PyLong_GetZero() | ||||
| #include "pycore_symtable.h"      // PySTEntryObject | ||||
| 
 | ||||
| #define NEED_OPCODE_JUMP_TABLES | ||||
| #define NEED_OPCODE_TABLES | ||||
| #include "opcode.h"               // EXTENDED_ARG | ||||
| 
 | ||||
| 
 | ||||
|  | @ -108,7 +108,7 @@ typedef struct exceptstack { | |||
| #define MASK_LOW_LOG_BITS 31 | ||||
| 
 | ||||
| static inline int | ||||
| is_bit_set_in_table(uint32_t *table, int bitindex) { | ||||
| is_bit_set_in_table(const uint32_t *table, int bitindex) { | ||||
|     /* Is the relevant bit set in the relevant word? */ | ||||
|     /* 256 bits fit into 8 32-bits words.
 | ||||
|      * Word is indexed by (bitindex>>ln(size of int in bits)). | ||||
|  |  | |||
|  | @ -59,7 +59,6 @@ static uint8_t adaptive_opcodes[256] = { | |||
| /* The number of cache entries required for a "family" of instructions. */ | ||||
| static uint8_t cache_requirements[256] = { | ||||
|     [LOAD_ATTR] = 1,  // _PyAdaptiveEntry
 | ||||
|     [LOAD_GLOBAL] = 2, /* _PyAdaptiveEntry and _PyLoadGlobalCache */ | ||||
|     [LOAD_METHOD] = 3, /* _PyAdaptiveEntry, _PyAttrCache and _PyObjectCache */ | ||||
|     [BINARY_SUBSCR] = 2, /* _PyAdaptiveEntry, _PyObjectCache */ | ||||
|     [STORE_SUBSCR] = 0, | ||||
|  | @ -1208,11 +1207,12 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, | |||
| int | ||||
| _Py_Specialize_LoadGlobal( | ||||
|     PyObject *globals, PyObject *builtins, | ||||
|     _Py_CODEUNIT *instr, PyObject *name, | ||||
|     SpecializedCacheEntry *cache) | ||||
|     _Py_CODEUNIT *instr, PyObject *name) | ||||
| { | ||||
|     _PyAdaptiveEntry *cache0 = &cache->adaptive; | ||||
|     _PyLoadGlobalCache *cache1 = &cache[-1].load_global; | ||||
|     assert(_PyOpcode_InlineCacheEntries[LOAD_GLOBAL] == | ||||
|            INLINE_CACHE_ENTRIES_LOAD_GLOBAL); | ||||
|     /* Use inline cache */ | ||||
|     _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)(instr + 1); | ||||
|     assert(PyUnicode_CheckExact(name)); | ||||
|     if (!PyDict_CheckExact(globals)) { | ||||
|         goto fail; | ||||
|  | @ -1231,8 +1231,8 @@ _Py_Specialize_LoadGlobal( | |||
|         if (keys_version == 0) { | ||||
|             goto fail; | ||||
|         } | ||||
|         cache1->module_keys_version = keys_version; | ||||
|         cache0->index = (uint16_t)index; | ||||
|         cache->index = (uint16_t)index; | ||||
|         write32(&cache->module_keys_version, keys_version); | ||||
|         *instr = _Py_MAKECODEUNIT(LOAD_GLOBAL_MODULE, _Py_OPARG(*instr)); | ||||
|         goto success; | ||||
|     } | ||||
|  | @ -1258,20 +1258,24 @@ _Py_Specialize_LoadGlobal( | |||
|         SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS); | ||||
|         goto fail; | ||||
|     } | ||||
|     cache1->module_keys_version = globals_version; | ||||
|     cache1->builtin_keys_version = builtins_version; | ||||
|     cache0->index = (uint16_t)index; | ||||
|     if (builtins_version > UINT16_MAX) { | ||||
|         SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE); | ||||
|         goto fail; | ||||
|     } | ||||
|     cache->index = (uint16_t)index; | ||||
|     write32(&cache->module_keys_version, globals_version); | ||||
|     cache->builtin_keys_version = (uint16_t)builtins_version; | ||||
|     *instr = _Py_MAKECODEUNIT(LOAD_GLOBAL_BUILTIN, _Py_OPARG(*instr)); | ||||
|     goto success; | ||||
| fail: | ||||
|     STAT_INC(LOAD_GLOBAL, failure); | ||||
|     assert(!PyErr_Occurred()); | ||||
|     cache_backoff(cache0); | ||||
|     cache->counter = ADAPTIVE_CACHE_BACKOFF; | ||||
|     return 0; | ||||
| success: | ||||
|     STAT_INC(LOAD_GLOBAL, success); | ||||
|     assert(!PyErr_Occurred()); | ||||
|     cache0->counter = initial_counter_value(); | ||||
|     cache->counter = initial_counter_value(); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Mark Shannon
						Mark Shannon