diff options
author | Pablo Galindo <Pablogsal@gmail.com> | 2020-10-20 05:22:44 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-20 05:22:44 (GMT) |
commit | 109826c8508dd02e06ae0f1784f1d202495a8680 (patch) | |
tree | 75b1dd3041d325b379cf50d2ebc5f6ce968fc151 /Objects | |
parent | 871934d4cf00687b3d1411c6e344af311646c1ae (diff) | |
download | cpython-109826c8508dd02e06ae0f1784f1d202495a8680.zip cpython-109826c8508dd02e06ae0f1784f1d202495a8680.tar.gz cpython-109826c8508dd02e06ae0f1784f1d202495a8680.tar.bz2 |
bpo-42093: Add opcode cache for LOAD_ATTR (GH-22803)
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/codeobject.c | 4 | ||||
-rw-r--r-- | Objects/dictobject.c | 65 |
2 files changed, 67 insertions, 2 deletions
diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 4ca22fc..c86d0e1 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -301,8 +301,8 @@ _PyCode_InitOpcache(PyCodeObject *co) unsigned char opcode = _Py_OPCODE(opcodes[i]); i++; // 'i' is now aligned to (next_instr - first_instr) - // TODO: LOAD_METHOD, LOAD_ATTR - if (opcode == LOAD_GLOBAL) { + // TODO: LOAD_METHOD + if (opcode == LOAD_GLOBAL || opcode == LOAD_ATTR) { opts++; co->co_opcache_map[i] = (unsigned char)opts; if (opts > 254) { diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 6c3fc62..8e74962 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1437,6 +1437,71 @@ PyDict_GetItem(PyObject *op, PyObject *key) return value; } +Py_ssize_t +_PyDict_GetItemHint(PyDictObject *mp, PyObject *key, + Py_ssize_t hint, PyObject **value) +{ + Py_hash_t hash; + PyThreadState *tstate; + + assert(*value == NULL); + assert(PyDict_CheckExact((PyObject*)mp)); + assert(PyUnicode_CheckExact(key)); + + if (hint >= 0 && hint < _PyDict_KeysSize(mp->ma_keys)) { + PyObject *res = NULL; + + PyDictKeyEntry *ep = DK_ENTRIES(mp->ma_keys) + (size_t)hint; + if (ep->me_key == key) { + if (mp->ma_keys->dk_lookup == lookdict_split) { + assert(mp->ma_values != NULL); + res = mp->ma_values[(size_t)hint]; + } + else { + res = ep->me_value; + } + if (res != NULL) { + *value = res; + return hint; + } + } + } + + if ((hash = ((PyASCIIObject *) key)->hash) == -1) + { + hash = PyObject_Hash(key); + if (hash == -1) { + PyErr_Clear(); + return -1; + } + } + + // We can arrive here with a NULL tstate during initialization: try + // running "python -Wi" for an example related to string interning + tstate = _PyThreadState_UncheckedGet(); + Py_ssize_t ix = 0; + if (tstate != NULL && tstate->curexc_type != NULL) { + /* preserve the existing exception */ + PyObject *err_type, *err_value, *err_tb; + PyErr_Fetch(&err_type, &err_value, &err_tb); + ix = (mp->ma_keys->dk_lookup)(mp, key, hash, value); + /* ignore errors */ + PyErr_Restore(err_type, err_value, err_tb); + if (ix < 0) { + return -1; + } + } + else { + ix = (mp->ma_keys->dk_lookup)(mp, key, hash, value); + if (ix < 0) { + PyErr_Clear(); + return -1; + } + } + + return ix; +} + /* Same as PyDict_GetItemWithError() but with hash supplied by caller. This returns NULL *with* an exception set if an exception occurred. It returns NULL *without* an exception set if the key wasn't present. |