diff options
author | Brandt Bucher <brandt@python.org> | 2021-10-27 02:45:35 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-27 10:45:35 +0100 |
commit | 82a662e5216a9b3969054c540a759a9493468510 (patch) | |
tree | 51bf9b433828dfd6d58f172097cf06202b54df9a /Python/ceval.c | |
parent | 19a6c41e56f129a67e2a3c96464ba893a97236f7 (diff) | |
download | cpython-git-82a662e5216a9b3969054c540a759a9493468510.tar.gz |
bpo-44511: Improve the bytecode for class and mapping patterns (GH-26922)
* Refactor mapping patterns and speed up class patterns.
* Simplify MATCH_KEYS and MATCH_CLASS.
* Add COPY opcode.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 68 |
1 files changed, 24 insertions, 44 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index adc7b53624..a0f4c801e8 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4143,25 +4143,30 @@ check_eval_breaker: } TARGET(MATCH_CLASS) { - // Pop TOS. On success, set TOS to True and TOS1 to a tuple of - // attributes. On failure, set TOS to False. + // Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or + // None on failure. PyObject *names = POP(); - PyObject *type = TOP(); - PyObject *subject = SECOND(); + PyObject *type = POP(); + PyObject *subject = TOP(); assert(PyTuple_CheckExact(names)); PyObject *attrs = match_class(tstate, subject, type, oparg, names); Py_DECREF(names); + Py_DECREF(type); if (attrs) { // Success! assert(PyTuple_CheckExact(attrs)); - Py_DECREF(subject); - SET_SECOND(attrs); + SET_TOP(attrs); } else if (_PyErr_Occurred(tstate)) { + // Error! goto error; } - Py_DECREF(type); - SET_TOP(PyBool_FromLong(!!attrs)); + else { + // Failure! + Py_INCREF(Py_None); + SET_TOP(Py_None); + } + Py_DECREF(subject); DISPATCH(); } @@ -4171,6 +4176,7 @@ check_eval_breaker: PyObject *res = match ? Py_True : Py_False; Py_INCREF(res); PUSH(res); + PREDICT(POP_JUMP_IF_FALSE); DISPATCH(); } @@ -4180,12 +4186,12 @@ check_eval_breaker: PyObject *res = match ? Py_True : Py_False; Py_INCREF(res); PUSH(res); + PREDICT(POP_JUMP_IF_FALSE); DISPATCH(); } TARGET(MATCH_KEYS) { - // On successful match for all keys, PUSH(values) and PUSH(True). - // Otherwise, PUSH(None) and PUSH(False). + // On successful match, PUSH(values). Otherwise, PUSH(None). PyObject *keys = TOP(); PyObject *subject = SECOND(); PyObject *values_or_none = match_keys(tstate, subject, keys); @@ -4193,40 +4199,6 @@ check_eval_breaker: goto error; } PUSH(values_or_none); - if (Py_IsNone(values_or_none)) { - Py_INCREF(Py_False); - PUSH(Py_False); - DISPATCH(); - } - assert(PyTuple_CheckExact(values_or_none)); - Py_INCREF(Py_True); - PUSH(Py_True); - DISPATCH(); - } - - TARGET(COPY_DICT_WITHOUT_KEYS) { - // rest = dict(TOS1) - // for key in TOS: - // del rest[key] - // SET_TOP(rest) - PyObject *keys = TOP(); - PyObject *subject = SECOND(); - PyObject *rest = PyDict_New(); - if (rest == NULL || PyDict_Update(rest, subject)) { - Py_XDECREF(rest); - goto error; - } - // This may seem a bit inefficient, but keys is rarely big enough to - // actually impact runtime. - assert(PyTuple_CheckExact(keys)); - for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(keys); i++) { - if (PyDict_DelItem(rest, PyTuple_GET_ITEM(keys, i))) { - Py_DECREF(rest); - goto error; - } - } - Py_DECREF(keys); - SET_TOP(rest); DISPATCH(); } @@ -5027,6 +4999,14 @@ check_eval_breaker: DISPATCH(); } + TARGET(COPY) { + assert(oparg != 0); + PyObject *peek = PEEK(oparg); + Py_INCREF(peek); + PUSH(peek); + DISPATCH(); + } + TARGET(EXTENDED_ARG) { int oldoparg = oparg; NEXTOPARG(); |