mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
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.
This commit is contained in:
parent
2abbd8f2ad
commit
069e81ab3d
16 changed files with 74 additions and 83 deletions
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -308,8 +308,6 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
|
|||
Py_CLEAR(interp->importlib);
|
||||
Py_CLEAR(interp->import_func);
|
||||
Py_CLEAR(interp->dict);
|
||||
Py_CLEAR(interp->map_abc);
|
||||
Py_CLEAR(interp->seq_abc);
|
||||
#ifdef HAVE_FORK
|
||||
Py_CLEAR(interp->before_forkers);
|
||||
Py_CLEAR(interp->after_forkers_parent);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue