mirror of
https://github.com/python/cpython.git
synced 2025-07-23 11:15:24 +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 @@ _specialized_instructions = [
|
||||||
"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 @@ check_eval_breaker:
|
||||||
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 @@ check_eval_breaker:
|
||||||
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 @@ binary_subscr_dict_error:
|
||||||
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