mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	bpo-44900: Add five superinstructions. (GH-27741)
* LOAD_FAST LOAD_FAST * STORE_FAST LOAD_FAST * LOAD_FAST LOAD_CONST * LOAD_CONST LOAD_FAST * STORE_FAST STORE_FAST
This commit is contained in:
		
							parent
							
								
									1a511dc92d
								
							
						
					
					
						commit
						4f51fa9e2d
					
				
					 6 changed files with 133 additions and 20 deletions
				
			
		
							
								
								
									
										5
									
								
								Include/opcode.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								Include/opcode.h
									
										
									
										generated
									
									
									
								
							|  | @ -153,6 +153,11 @@ extern "C" { | ||||||
| #define STORE_ATTR_SPLIT_KEYS    45 | #define STORE_ATTR_SPLIT_KEYS    45 | ||||||
| #define STORE_ATTR_SLOT          46 | #define STORE_ATTR_SLOT          46 | ||||||
| #define STORE_ATTR_WITH_HINT     47 | #define STORE_ATTR_WITH_HINT     47 | ||||||
|  | #define LOAD_FAST__LOAD_FAST     48 | ||||||
|  | #define STORE_FAST__LOAD_FAST    58 | ||||||
|  | #define LOAD_FAST__LOAD_CONST    80 | ||||||
|  | #define LOAD_CONST__LOAD_FAST    81 | ||||||
|  | #define STORE_FAST__STORE_FAST   87 | ||||||
| #ifdef NEED_OPCODE_JUMP_TABLES | #ifdef NEED_OPCODE_JUMP_TABLES | ||||||
| static uint32_t _PyOpcode_RelativeJump[8] = { | static uint32_t _PyOpcode_RelativeJump[8] = { | ||||||
|     0U, |     0U, | ||||||
|  |  | ||||||
|  | @ -237,8 +237,13 @@ def jabs_op(name, op): | ||||||
|     "STORE_ATTR_SPLIT_KEYS", |     "STORE_ATTR_SPLIT_KEYS", | ||||||
|     "STORE_ATTR_SLOT", |     "STORE_ATTR_SLOT", | ||||||
|     "STORE_ATTR_WITH_HINT", |     "STORE_ATTR_WITH_HINT", | ||||||
|  |     # Super instructions | ||||||
|  |     "LOAD_FAST__LOAD_FAST", | ||||||
|  |     "STORE_FAST__LOAD_FAST", | ||||||
|  |     "LOAD_FAST__LOAD_CONST", | ||||||
|  |     "LOAD_CONST__LOAD_FAST", | ||||||
|  |     "STORE_FAST__STORE_FAST", | ||||||
| ] | ] | ||||||
| 
 |  | ||||||
| _specialization_stats = [ | _specialization_stats = [ | ||||||
|     "specialization_success", |     "specialization_success", | ||||||
|     "specialization_failure", |     "specialization_failure", | ||||||
|  |  | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | Add five superinstructions for PEP 659 quickening: | ||||||
|  | 
 | ||||||
|  | * LOAD_FAST LOAD_FAST | ||||||
|  | * STORE_FAST LOAD_FAST | ||||||
|  | * LOAD_FAST LOAD_CONST | ||||||
|  | * LOAD_CONST LOAD_FAST | ||||||
|  | * STORE_FAST STORE_FAST | ||||||
|  | @ -1266,16 +1266,21 @@ eval_frame_handle_pending(PyThreadState *tstate) | ||||||
| #define PRE_DISPATCH_GOTO() do { LLTRACE_INSTR();  RECORD_DXPROFILE(); } while (0) | #define PRE_DISPATCH_GOTO() do { LLTRACE_INSTR();  RECORD_DXPROFILE(); } while (0) | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #define NOTRACE_DISPATCH() \ | ||||||
|  |     { \ | ||||||
|  |         frame->f_lasti = INSTR_OFFSET(); \ | ||||||
|  |         NEXTOPARG(); \ | ||||||
|  |         PRE_DISPATCH_GOTO(); \ | ||||||
|  |         DISPATCH_GOTO(); \ | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| /* Do interpreter dispatch accounting for tracing and instrumentation */ | /* Do interpreter dispatch accounting for tracing and instrumentation */ | ||||||
| #define DISPATCH() \ | #define DISPATCH() \ | ||||||
|     { \ |     { \ | ||||||
|         if (cframe.use_tracing OR_DTRACE_LINE) { \ |         if (cframe.use_tracing OR_DTRACE_LINE) { \ | ||||||
|             goto tracing_dispatch; \ |             goto tracing_dispatch; \ | ||||||
|         } \ |         } \ | ||||||
|         frame->f_lasti = INSTR_OFFSET(); \ |         NOTRACE_DISPATCH(); \ | ||||||
|         NEXTOPARG(); \ |  | ||||||
|         PRE_DISPATCH_GOTO(); \ |  | ||||||
|         DISPATCH_GOTO(); \ |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| #define CHECK_EVAL_BREAKER() \ | #define CHECK_EVAL_BREAKER() \ | ||||||
|  | @ -1682,11 +1687,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr | ||||||
|         TARGET(LOAD_FAST): { |         TARGET(LOAD_FAST): { | ||||||
|             PyObject *value = GETLOCAL(oparg); |             PyObject *value = GETLOCAL(oparg); | ||||||
|             if (value == NULL) { |             if (value == NULL) { | ||||||
|                 format_exc_check_arg(tstate, PyExc_UnboundLocalError, |                 goto unbound_local_error; | ||||||
|                                      UNBOUNDLOCAL_ERROR_MSG, |  | ||||||
|                                      PyTuple_GetItem(co->co_localsplusnames, |  | ||||||
|                                                      oparg)); |  | ||||||
|                 goto error; |  | ||||||
|             } |             } | ||||||
|             Py_INCREF(value); |             Py_INCREF(value); | ||||||
|             PUSH(value); |             PUSH(value); | ||||||
|  | @ -1708,6 +1709,73 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr | ||||||
|             DISPATCH(); |             DISPATCH(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         TARGET(LOAD_FAST__LOAD_FAST): { | ||||||
|  |             PyObject *value = GETLOCAL(oparg); | ||||||
|  |             if (value == NULL) { | ||||||
|  |                 goto unbound_local_error; | ||||||
|  |             } | ||||||
|  |             NEXTOPARG(); | ||||||
|  |             Py_INCREF(value); | ||||||
|  |             PUSH(value); | ||||||
|  |             value = GETLOCAL(oparg); | ||||||
|  |             if (value == NULL) { | ||||||
|  |                 goto unbound_local_error; | ||||||
|  |             } | ||||||
|  |             Py_INCREF(value); | ||||||
|  |             PUSH(value); | ||||||
|  |             NOTRACE_DISPATCH(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         TARGET(LOAD_FAST__LOAD_CONST): { | ||||||
|  |             PyObject *value = GETLOCAL(oparg); | ||||||
|  |             if (value == NULL) { | ||||||
|  |                 goto unbound_local_error; | ||||||
|  |             } | ||||||
|  |             NEXTOPARG(); | ||||||
|  |             Py_INCREF(value); | ||||||
|  |             PUSH(value); | ||||||
|  |             value = GETITEM(consts, oparg); | ||||||
|  |             Py_INCREF(value); | ||||||
|  |             PUSH(value); | ||||||
|  |             NOTRACE_DISPATCH(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         TARGET(STORE_FAST__LOAD_FAST): { | ||||||
|  |             PyObject *value = POP(); | ||||||
|  |             SETLOCAL(oparg, value); | ||||||
|  |             NEXTOPARG(); | ||||||
|  |             value = GETLOCAL(oparg); | ||||||
|  |             if (value == NULL) { | ||||||
|  |                 goto unbound_local_error; | ||||||
|  |             } | ||||||
|  |             Py_INCREF(value); | ||||||
|  |             PUSH(value); | ||||||
|  |             NOTRACE_DISPATCH(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         TARGET(STORE_FAST__STORE_FAST): { | ||||||
|  |             PyObject *value = POP(); | ||||||
|  |             SETLOCAL(oparg, value); | ||||||
|  |             NEXTOPARG(); | ||||||
|  |             value = POP(); | ||||||
|  |             SETLOCAL(oparg, value); | ||||||
|  |             NOTRACE_DISPATCH(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         TARGET(LOAD_CONST__LOAD_FAST): { | ||||||
|  |             PyObject *value = GETITEM(consts, oparg); | ||||||
|  |             NEXTOPARG(); | ||||||
|  |             Py_INCREF(value); | ||||||
|  |             PUSH(value); | ||||||
|  |             value = GETLOCAL(oparg); | ||||||
|  |             if (value == NULL) { | ||||||
|  |                 goto unbound_local_error; | ||||||
|  |             } | ||||||
|  |             Py_INCREF(value); | ||||||
|  |             PUSH(value); | ||||||
|  |             NOTRACE_DISPATCH(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         TARGET(POP_TOP): { |         TARGET(POP_TOP): { | ||||||
|             PyObject *value = POP(); |             PyObject *value = POP(); | ||||||
|             Py_DECREF(value); |             Py_DECREF(value); | ||||||
|  | @ -4592,6 +4660,15 @@ MISS_WITH_OPARG_COUNTER(BINARY_SUBSCR) | ||||||
|             goto error; |             goto error; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | unbound_local_error: | ||||||
|  |         { | ||||||
|  |             format_exc_check_arg(tstate, PyExc_UnboundLocalError, | ||||||
|  |                 UNBOUNDLOCAL_ERROR_MSG, | ||||||
|  |                 PyTuple_GetItem(co->co_localsplusnames, oparg) | ||||||
|  |             ); | ||||||
|  |             goto error; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
| error: | error: | ||||||
|         /* Double-check exception status. */ |         /* Double-check exception status. */ | ||||||
| #ifdef NDEBUG | #ifdef NDEBUG | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								Python/opcode_targets.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										10
									
								
								Python/opcode_targets.h
									
										
									
										generated
									
									
									
								
							|  | @ -47,7 +47,7 @@ static void *opcode_targets[256] = { | ||||||
|     &&TARGET_STORE_ATTR_SPLIT_KEYS, |     &&TARGET_STORE_ATTR_SPLIT_KEYS, | ||||||
|     &&TARGET_STORE_ATTR_SLOT, |     &&TARGET_STORE_ATTR_SLOT, | ||||||
|     &&TARGET_STORE_ATTR_WITH_HINT, |     &&TARGET_STORE_ATTR_WITH_HINT, | ||||||
|     &&_unknown_opcode, |     &&TARGET_LOAD_FAST__LOAD_FAST, | ||||||
|     &&TARGET_WITH_EXCEPT_START, |     &&TARGET_WITH_EXCEPT_START, | ||||||
|     &&TARGET_GET_AITER, |     &&TARGET_GET_AITER, | ||||||
|     &&TARGET_GET_ANEXT, |     &&TARGET_GET_ANEXT, | ||||||
|  | @ -57,7 +57,7 @@ static void *opcode_targets[256] = { | ||||||
|     &&TARGET_INPLACE_ADD, |     &&TARGET_INPLACE_ADD, | ||||||
|     &&TARGET_INPLACE_SUBTRACT, |     &&TARGET_INPLACE_SUBTRACT, | ||||||
|     &&TARGET_INPLACE_MULTIPLY, |     &&TARGET_INPLACE_MULTIPLY, | ||||||
|     &&_unknown_opcode, |     &&TARGET_STORE_FAST__LOAD_FAST, | ||||||
|     &&TARGET_INPLACE_MODULO, |     &&TARGET_INPLACE_MODULO, | ||||||
|     &&TARGET_STORE_SUBSCR, |     &&TARGET_STORE_SUBSCR, | ||||||
|     &&TARGET_DELETE_SUBSCR, |     &&TARGET_DELETE_SUBSCR, | ||||||
|  | @ -79,14 +79,14 @@ static void *opcode_targets[256] = { | ||||||
|     &&TARGET_INPLACE_AND, |     &&TARGET_INPLACE_AND, | ||||||
|     &&TARGET_INPLACE_XOR, |     &&TARGET_INPLACE_XOR, | ||||||
|     &&TARGET_INPLACE_OR, |     &&TARGET_INPLACE_OR, | ||||||
|     &&_unknown_opcode, |     &&TARGET_LOAD_FAST__LOAD_CONST, | ||||||
|     &&_unknown_opcode, |     &&TARGET_LOAD_CONST__LOAD_FAST, | ||||||
|     &&TARGET_LIST_TO_TUPLE, |     &&TARGET_LIST_TO_TUPLE, | ||||||
|     &&TARGET_RETURN_VALUE, |     &&TARGET_RETURN_VALUE, | ||||||
|     &&TARGET_IMPORT_STAR, |     &&TARGET_IMPORT_STAR, | ||||||
|     &&TARGET_SETUP_ANNOTATIONS, |     &&TARGET_SETUP_ANNOTATIONS, | ||||||
|     &&TARGET_YIELD_VALUE, |     &&TARGET_YIELD_VALUE, | ||||||
|     &&_unknown_opcode, |     &&TARGET_STORE_FAST__STORE_FAST, | ||||||
|     &&_unknown_opcode, |     &&_unknown_opcode, | ||||||
|     &&TARGET_POP_EXCEPT, |     &&TARGET_POP_EXCEPT, | ||||||
|     &&TARGET_STORE_NAME, |     &&TARGET_STORE_NAME, | ||||||
|  |  | ||||||
|  | @ -303,6 +303,7 @@ optimize(SpecializedCacheOrInstruction *quickened, int len) | ||||||
|     _Py_CODEUNIT *instructions = first_instruction(quickened); |     _Py_CODEUNIT *instructions = first_instruction(quickened); | ||||||
|     int cache_offset = 0; |     int cache_offset = 0; | ||||||
|     int previous_opcode = -1; |     int previous_opcode = -1; | ||||||
|  |     int previous_oparg = 0; | ||||||
|     for(int i = 0; i < len; i++) { |     for(int i = 0; i < len; i++) { | ||||||
|         int opcode = _Py_OPCODE(instructions[i]); |         int opcode = _Py_OPCODE(instructions[i]); | ||||||
|         int oparg = _Py_OPARG(instructions[i]); |         int oparg = _Py_OPARG(instructions[i]); | ||||||
|  | @ -338,14 +339,32 @@ optimize(SpecializedCacheOrInstruction *quickened, int len) | ||||||
|                 case JUMP_ABSOLUTE: |                 case JUMP_ABSOLUTE: | ||||||
|                     instructions[i] = _Py_MAKECODEUNIT(JUMP_ABSOLUTE_QUICK, oparg); |                     instructions[i] = _Py_MAKECODEUNIT(JUMP_ABSOLUTE_QUICK, oparg); | ||||||
|                     break; |                     break; | ||||||
|                 /* Insert superinstructions here
 |  | ||||||
|                  E.g. |  | ||||||
|                 case LOAD_FAST: |                 case LOAD_FAST: | ||||||
|                     if (previous_opcode == LOAD_FAST) |                     switch(previous_opcode) { | ||||||
|                         instructions[i-1] = _Py_MAKECODEUNIT(LOAD_FAST__LOAD_FAST, oparg); |                         case LOAD_FAST: | ||||||
|                  */ |                             instructions[i-1] = _Py_MAKECODEUNIT(LOAD_FAST__LOAD_FAST, previous_oparg); | ||||||
|  |                             break; | ||||||
|  |                         case STORE_FAST: | ||||||
|  |                             instructions[i-1] = _Py_MAKECODEUNIT(STORE_FAST__LOAD_FAST, previous_oparg); | ||||||
|  |                             break; | ||||||
|  |                         case LOAD_CONST: | ||||||
|  |                             instructions[i-1] = _Py_MAKECODEUNIT(LOAD_CONST__LOAD_FAST, previous_oparg); | ||||||
|  |                             break; | ||||||
|  |                     } | ||||||
|  |                     break; | ||||||
|  |                 case STORE_FAST: | ||||||
|  |                     if (previous_opcode == STORE_FAST) { | ||||||
|  |                         instructions[i-1] = _Py_MAKECODEUNIT(STORE_FAST__STORE_FAST, previous_oparg); | ||||||
|  |                     } | ||||||
|  |                     break; | ||||||
|  |                 case LOAD_CONST: | ||||||
|  |                     if (previous_opcode == LOAD_FAST) { | ||||||
|  |                         instructions[i-1] = _Py_MAKECODEUNIT(LOAD_FAST__LOAD_CONST, previous_oparg); | ||||||
|  |                     } | ||||||
|  |                     break; | ||||||
|             } |             } | ||||||
|             previous_opcode = opcode; |             previous_opcode = opcode; | ||||||
|  |             previous_oparg = oparg; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     assert(cache_offset+1 == get_cache_count(quickened)); |     assert(cache_offset+1 == get_cache_count(quickened)); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Mark Shannon
						Mark Shannon