diff options
author | Mark Shannon <mark@hotpy.org> | 2021-11-18 11:02:14 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-18 11:02:14 (GMT) |
commit | 21fa7a3e8f99a1a32467f85c877e40cbdafa9da7 (patch) | |
tree | 55d139caef014d3875f2cd65de98f52f8669d78d /Python/ceval.c | |
parent | 5275e59c0c1b26226608e6c7c2548c26192d6575 (diff) | |
download | cpython-21fa7a3e8f99a1a32467f85c877e40cbdafa9da7.zip cpython-21fa7a3e8f99a1a32467f85c877e40cbdafa9da7.tar.gz cpython-21fa7a3e8f99a1a32467f85c877e40cbdafa9da7.tar.bz2 |
bpo-45829: Specialize BINARY_SUBSCR for __getitem__ implemented in Python. (GH-29592)
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index e579ede..2b7b31c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2140,21 +2140,21 @@ check_eval_breaker: } TARGET(BINARY_SUBSCR_ADAPTIVE) { - if (oparg == 0) { + SpecializedCacheEntry *cache = GET_CACHE(); + if (cache->adaptive.counter == 0) { PyObject *sub = TOP(); PyObject *container = SECOND(); next_instr--; - if (_Py_Specialize_BinarySubscr(container, sub, next_instr) < 0) { + if (_Py_Specialize_BinarySubscr(container, sub, next_instr, cache) < 0) { goto error; } DISPATCH(); } else { STAT_INC(BINARY_SUBSCR, deferred); - // oparg is the adaptive cache counter - UPDATE_PREV_INSTR_OPARG(next_instr, oparg - 1); - assert(_Py_OPCODE(next_instr[-1]) == BINARY_SUBSCR_ADAPTIVE); - assert(_Py_OPARG(next_instr[-1]) == oparg - 1); + cache->adaptive.counter--; + assert(cache->adaptive.original_oparg == 0); + /* No need to set oparg here; it isn't used by BINARY_SUBSCR */ STAT_DEC(BINARY_SUBSCR, unquickened); JUMP_TO_INSTRUCTION(BINARY_SUBSCR); } @@ -2223,6 +2223,37 @@ check_eval_breaker: DISPATCH(); } + TARGET(BINARY_SUBSCR_GETITEM) { + PyObject *sub = TOP(); + PyObject *container = SECOND(); + SpecializedCacheEntry *caches = GET_CACHE(); + _PyAdaptiveEntry *cache0 = &caches[0].adaptive; + _PyObjectCache *cache1 = &caches[-1].obj; + PyFunctionObject *getitem = (PyFunctionObject *)cache1->obj; + DEOPT_IF(Py_TYPE(container)->tp_version_tag != cache0->version, BINARY_SUBSCR); + DEOPT_IF(getitem->func_version != cache0->index, BINARY_SUBSCR); + PyCodeObject *code = (PyCodeObject *)getitem->func_code; + size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE; + assert(code->co_argcount == 2); + InterpreterFrame *new_frame = _PyThreadState_BumpFramePointer(tstate, size); + if (new_frame == NULL) { + goto error; + } + _PyFrame_InitializeSpecials(new_frame, PyFunction_AS_FRAME_CONSTRUCTOR(getitem), + NULL, code->co_nlocalsplus); + STACK_SHRINK(2); + new_frame->localsplus[0] = container; + new_frame->localsplus[1] = sub; + for (int i = 2; i < code->co_nlocalsplus; i++) { + new_frame->localsplus[i] = NULL; + } + _PyFrame_SetStackPointer(frame, stack_pointer); + new_frame->previous = frame; + frame = cframe.current_frame = new_frame; + new_frame->depth = frame->depth + 1; + goto start_frame; + } + TARGET(LIST_APPEND) { PyObject *v = POP(); PyObject *list = PEEK(oparg); @@ -4878,29 +4909,13 @@ opname ## _miss: \ JUMP_TO_INSTRUCTION(opname); \ } -#define MISS_WITH_OPARG_COUNTER(opname) \ -opname ## _miss: \ - { \ - STAT_INC(opname, miss); \ - uint8_t oparg = _Py_OPARG(next_instr[-1])-1; \ - UPDATE_PREV_INSTR_OPARG(next_instr, oparg); \ - assert(_Py_OPARG(next_instr[-1]) == oparg); \ - if (oparg == 0) /* too many cache misses */ { \ - oparg = ADAPTIVE_CACHE_BACKOFF; \ - next_instr[-1] = _Py_MAKECODEUNIT(opname ## _ADAPTIVE, oparg); \ - STAT_INC(opname, deopt); \ - } \ - STAT_DEC(opname, unquickened); \ - JUMP_TO_INSTRUCTION(opname); \ - } - MISS_WITH_CACHE(LOAD_ATTR) MISS_WITH_CACHE(STORE_ATTR) MISS_WITH_CACHE(LOAD_GLOBAL) MISS_WITH_CACHE(LOAD_METHOD) MISS_WITH_CACHE(CALL_FUNCTION) MISS_WITH_CACHE(BINARY_OP) -MISS_WITH_OPARG_COUNTER(BINARY_SUBSCR) +MISS_WITH_CACHE(BINARY_SUBSCR) binary_subscr_dict_error: { |