summaryrefslogtreecommitdiff
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorBrandt Bucher <brandt@python.org>2021-10-27 02:45:35 -0700
committerGitHub <noreply@github.com>2021-10-27 10:45:35 +0100
commit82a662e5216a9b3969054c540a759a9493468510 (patch)
tree51bf9b433828dfd6d58f172097cf06202b54df9a /Python/ceval.c
parent19a6c41e56f129a67e2a3c96464ba893a97236f7 (diff)
downloadcpython-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.c68
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();