diff options
author | Mark Shannon <mark@hotpy.org> | 2021-08-16 11:23:13 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-16 11:23:13 (GMT) |
commit | 4f51fa9e2d3ea9316e674fb9a9f3e3112e83661c (patch) | |
tree | e53e8b3f636de346a7abba7875aae03d234ce299 /Python | |
parent | 1a511dc92dd10ee8fc2e5da9f52f795924bdc89a (diff) | |
download | cpython-4f51fa9e2d3ea9316e674fb9a9f3e3112e83661c.zip cpython-4f51fa9e2d3ea9316e674fb9a9f3e3112e83661c.tar.gz cpython-4f51fa9e2d3ea9316e674fb9a9f3e3112e83661c.tar.bz2 |
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
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 95 | ||||
-rw-r--r-- | Python/opcode_targets.h | 10 | ||||
-rw-r--r-- | Python/specialize.c | 29 |
3 files changed, 115 insertions, 19 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 111689f..4878749 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1266,16 +1266,21 @@ eval_frame_handle_pending(PyThreadState *tstate) #define PRE_DISPATCH_GOTO() do { LLTRACE_INSTR(); RECORD_DXPROFILE(); } while (0) #endif +#define NOTRACE_DISPATCH() \ + { \ + frame->f_lasti = INSTR_OFFSET(); \ + NEXTOPARG(); \ + PRE_DISPATCH_GOTO(); \ + DISPATCH_GOTO(); \ + } + /* Do interpreter dispatch accounting for tracing and instrumentation */ #define DISPATCH() \ { \ if (cframe.use_tracing OR_DTRACE_LINE) { \ goto tracing_dispatch; \ } \ - frame->f_lasti = INSTR_OFFSET(); \ - NEXTOPARG(); \ - PRE_DISPATCH_GOTO(); \ - DISPATCH_GOTO(); \ + NOTRACE_DISPATCH(); \ } #define CHECK_EVAL_BREAKER() \ @@ -1682,11 +1687,7 @@ check_eval_breaker: TARGET(LOAD_FAST): { PyObject *value = GETLOCAL(oparg); if (value == NULL) { - format_exc_check_arg(tstate, PyExc_UnboundLocalError, - UNBOUNDLOCAL_ERROR_MSG, - PyTuple_GetItem(co->co_localsplusnames, - oparg)); - goto error; + goto unbound_local_error; } Py_INCREF(value); PUSH(value); @@ -1708,6 +1709,73 @@ check_eval_breaker: 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): { PyObject *value = POP(); Py_DECREF(value); @@ -4592,6 +4660,15 @@ binary_subscr_dict_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: /* Double-check exception status. */ #ifdef NDEBUG diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 24ee44f..c8036a6 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -47,7 +47,7 @@ static void *opcode_targets[256] = { &&TARGET_STORE_ATTR_SPLIT_KEYS, &&TARGET_STORE_ATTR_SLOT, &&TARGET_STORE_ATTR_WITH_HINT, - &&_unknown_opcode, + &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_WITH_EXCEPT_START, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, @@ -57,7 +57,7 @@ static void *opcode_targets[256] = { &&TARGET_INPLACE_ADD, &&TARGET_INPLACE_SUBTRACT, &&TARGET_INPLACE_MULTIPLY, - &&_unknown_opcode, + &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_INPLACE_MODULO, &&TARGET_STORE_SUBSCR, &&TARGET_DELETE_SUBSCR, @@ -79,14 +79,14 @@ static void *opcode_targets[256] = { &&TARGET_INPLACE_AND, &&TARGET_INPLACE_XOR, &&TARGET_INPLACE_OR, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_LOAD_FAST__LOAD_CONST, + &&TARGET_LOAD_CONST__LOAD_FAST, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, &&TARGET_SETUP_ANNOTATIONS, &&TARGET_YIELD_VALUE, - &&_unknown_opcode, + &&TARGET_STORE_FAST__STORE_FAST, &&_unknown_opcode, &&TARGET_POP_EXCEPT, &&TARGET_STORE_NAME, diff --git a/Python/specialize.c b/Python/specialize.c index e653ae4..ecab69b 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -303,6 +303,7 @@ optimize(SpecializedCacheOrInstruction *quickened, int len) _Py_CODEUNIT *instructions = first_instruction(quickened); int cache_offset = 0; int previous_opcode = -1; + int previous_oparg = 0; for(int i = 0; i < len; i++) { int opcode = _Py_OPCODE(instructions[i]); int oparg = _Py_OPARG(instructions[i]); @@ -338,14 +339,32 @@ optimize(SpecializedCacheOrInstruction *quickened, int len) case JUMP_ABSOLUTE: instructions[i] = _Py_MAKECODEUNIT(JUMP_ABSOLUTE_QUICK, oparg); break; - /* Insert superinstructions here - E.g. case LOAD_FAST: - if (previous_opcode == LOAD_FAST) - instructions[i-1] = _Py_MAKECODEUNIT(LOAD_FAST__LOAD_FAST, oparg); - */ + switch(previous_opcode) { + 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_oparg = oparg; } } assert(cache_offset+1 == get_cache_count(quickened)); |