aboutsummaryrefslogtreecommitdiff
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2021-04-30 09:50:28 +0100
committerGitHub <noreply@github.com>2021-04-30 09:50:28 +0100
commit069e81ab3da46c441335ca762c4333b7bd91861d (patch)
tree02716907f4513a812cf2c72309cc4e6f133b3ab3 /Python/ceval.c
parent2abbd8f2add5e80b86a965625b9a77ae94a101cd (diff)
downloadcpython3-069e81ab3da46c441335ca762c4333b7bd91861d.tar.gz
bpo-43977: Use tp_flags for collection matching (GH-25723)
* Add Py_TPFLAGS_SEQUENCE and Py_TPFLAGS_MAPPING, add to all relevant standard builtin classes. * Set relevant flags on collections.abc.Sequence and Mapping. * Use flags in MATCH_SEQUENCE and MATCH_MAPPING opcodes. * Inherit Py_TPFLAGS_SEQUENCE and Py_TPFLAGS_MAPPING. * Add NEWS * Remove interpreter-state map_abc and seq_abc fields.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c72
1 files changed, 8 insertions, 64 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 326930b706..866c57afdb 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -3889,76 +3889,20 @@ main_loop:
}
case TARGET(MATCH_MAPPING): {
- // PUSH(isinstance(TOS, _collections_abc.Mapping))
PyObject *subject = TOP();
- // Fast path for dicts:
- if (PyDict_Check(subject)) {
- Py_INCREF(Py_True);
- PUSH(Py_True);
- DISPATCH();
- }
- // Lazily import _collections_abc.Mapping, and keep it handy on the
- // PyInterpreterState struct (it gets cleaned up at exit):
- PyInterpreterState *interp = PyInterpreterState_Get();
- if (interp->map_abc == NULL) {
- PyObject *abc = PyImport_ImportModule("_collections_abc");
- if (abc == NULL) {
- goto error;
- }
- interp->map_abc = PyObject_GetAttrString(abc, "Mapping");
- if (interp->map_abc == NULL) {
- goto error;
- }
- }
- int match = PyObject_IsInstance(subject, interp->map_abc);
- if (match < 0) {
- goto error;
- }
- PUSH(PyBool_FromLong(match));
+ int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING;
+ PyObject *res = match ? Py_True : Py_False;
+ Py_INCREF(res);
+ PUSH(res);
DISPATCH();
}
case TARGET(MATCH_SEQUENCE): {
- // PUSH(not isinstance(TOS, (bytearray, bytes, str))
- // and isinstance(TOS, _collections_abc.Sequence))
PyObject *subject = TOP();
- // Fast path for lists and tuples:
- if (PyType_FastSubclass(Py_TYPE(subject),
- Py_TPFLAGS_LIST_SUBCLASS |
- Py_TPFLAGS_TUPLE_SUBCLASS))
- {
- Py_INCREF(Py_True);
- PUSH(Py_True);
- DISPATCH();
- }
- // Bail on some possible Sequences that we intentionally exclude:
- if (PyType_FastSubclass(Py_TYPE(subject),
- Py_TPFLAGS_BYTES_SUBCLASS |
- Py_TPFLAGS_UNICODE_SUBCLASS) ||
- PyByteArray_Check(subject))
- {
- Py_INCREF(Py_False);
- PUSH(Py_False);
- DISPATCH();
- }
- // Lazily import _collections_abc.Sequence, and keep it handy on the
- // PyInterpreterState struct (it gets cleaned up at exit):
- PyInterpreterState *interp = PyInterpreterState_Get();
- if (interp->seq_abc == NULL) {
- PyObject *abc = PyImport_ImportModule("_collections_abc");
- if (abc == NULL) {
- goto error;
- }
- interp->seq_abc = PyObject_GetAttrString(abc, "Sequence");
- if (interp->seq_abc == NULL) {
- goto error;
- }
- }
- int match = PyObject_IsInstance(subject, interp->seq_abc);
- if (match < 0) {
- goto error;
- }
- PUSH(PyBool_FromLong(match));
+ int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE;
+ PyObject *res = match ? Py_True : Py_False;
+ Py_INCREF(res);
+ PUSH(res);
DISPATCH();
}