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: | 
