diff options
author | Ken Jin <kenjin4096@gmail.com> | 2022-05-25 13:06:15 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-25 13:06:15 (GMT) |
commit | 5e6e5b98a8b943a8e05feb9c0c982150565f4c10 (patch) | |
tree | 6dd6c8e8057ff014fcc365db4fe83dad0bf3aea6 /Python/specialize.c | |
parent | db3ef0c82a1a16db60c35f8a08c3fd9bfaa8b643 (diff) | |
download | cpython-5e6e5b98a8b943a8e05feb9c0c982150565f4c10.zip cpython-5e6e5b98a8b943a8e05feb9c0c982150565f4c10.tar.gz cpython-5e6e5b98a8b943a8e05feb9c0c982150565f4c10.tar.bz2 |
gh-92777: Add LOAD_METHOD_LAZY_DICT (GH-92778)
Diffstat (limited to 'Python/specialize.c')
-rw-r--r-- | Python/specialize.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/Python/specialize.c b/Python/specialize.c index 9579369..7148b5d 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -903,7 +903,8 @@ typedef enum { MANAGED_VALUES = 1, MANAGED_DICT = 2, OFFSET_DICT = 3, - NO_DICT = 4 + NO_DICT = 4, + LAZY_DICT = 5, } ObjectDictKind; // Please collect stats carefully before and after modifying. A subtle change @@ -972,14 +973,17 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) else { PyObject *dict = *(PyObject **) ((char *)owner + dictoffset); if (dict == NULL) { - SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_NO_DICT); - goto fail; + // This object will have a dict if user access __dict__ + dictkind = LAZY_DICT; + keys = NULL; + } + else { + keys = ((PyDictObject *)dict)->ma_keys; + dictkind = OFFSET_DICT; } - keys = ((PyDictObject *)dict)->ma_keys; - dictkind = OFFSET_DICT; } } - if (dictkind != NO_DICT) { + if (dictkind == MANAGED_VALUES || dictkind == MANAGED_DICT || dictkind == OFFSET_DICT) { Py_ssize_t index = _PyDictKeys_StringLookup(keys, name); if (index != DKIX_EMPTY) { SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_LOAD_METHOD_IS_ATTR); @@ -1008,6 +1012,11 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) cache->dict_offset = (uint16_t)owner_cls->tp_dictoffset; _Py_SET_OPCODE(*instr, LOAD_METHOD_WITH_DICT); break; + case LAZY_DICT: + assert(owner_cls->tp_dictoffset > 0 && owner_cls->tp_dictoffset <= INT16_MAX); + cache->dict_offset = (uint16_t)owner_cls->tp_dictoffset; + _Py_SET_OPCODE(*instr, LOAD_METHOD_LAZY_DICT); + break; } /* `descr` is borrowed. This is safe for methods (even inherited ones from * super classes!) as long as tp_version_tag is validated for two main reasons: |