summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorDong-hee Na <donghee.na@python.org>2021-08-30 10:02:32 (GMT)
committerGitHub <noreply@github.com>2021-08-30 10:02:32 (GMT)
commite6497fe698f6e87344501a68ffdea106eafcb257 (patch)
tree718e80e25ac74a37c9f202930fa0171b7e2d8509 /Python
parent94b2639fad50d7ff8acd12c11e5fe5f9a6e1da5c (diff)
downloadcpython-e6497fe698f6e87344501a68ffdea106eafcb257.zip
cpython-e6497fe698f6e87344501a68ffdea106eafcb257.tar.gz
cpython-e6497fe698f6e87344501a68ffdea106eafcb257.tar.bz2
bpo-45045: Optimize mapping patterns of structural pattern matching (GH-28043)
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 8aaa83b..bf95d50 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -841,12 +841,18 @@ match_keys(PyThreadState *tstate, PyObject *map, PyObject *keys)
PyObject *seen = NULL;
PyObject *dummy = NULL;
PyObject *values = NULL;
+ PyObject *get_name = NULL;
+ PyObject *get = NULL;
// We use the two argument form of map.get(key, default) for two reasons:
// - Atomically check for a key and get its value without error handling.
// - Don't cause key creation or resizing in dict subclasses like
// collections.defaultdict that define __missing__ (or similar).
_Py_IDENTIFIER(get);
- PyObject *get = _PyObject_GetAttrId(map, &PyId_get);
+ get_name = _PyUnicode_FromId(&PyId_get); // borrowed
+ if (get_name == NULL) {
+ return NULL;
+ }
+ int meth_found = _PyObject_GetMethod(map, get_name, &get);
if (get == NULL) {
goto fail;
}
@@ -859,7 +865,7 @@ match_keys(PyThreadState *tstate, PyObject *map, PyObject *keys)
if (dummy == NULL) {
goto fail;
}
- values = PyList_New(0);
+ values = PyTuple_New(nkeys);
if (values == NULL) {
goto fail;
}
@@ -873,7 +879,14 @@ match_keys(PyThreadState *tstate, PyObject *map, PyObject *keys)
}
goto fail;
}
- PyObject *value = PyObject_CallFunctionObjArgs(get, key, dummy, NULL);
+ PyObject *args[] = { map, key, dummy };
+ PyObject *value = NULL;
+ if (meth_found) {
+ value = PyObject_Vectorcall(get, args, 3, NULL);
+ }
+ else {
+ value = PyObject_Vectorcall(get, &args[1], 2, NULL);
+ }
if (value == NULL) {
goto fail;
}
@@ -886,10 +899,8 @@ match_keys(PyThreadState *tstate, PyObject *map, PyObject *keys)
values = Py_None;
goto done;
}
- PyList_Append(values, value);
- Py_DECREF(value);
+ PyTuple_SET_ITEM(values, i, value);
}
- Py_SETREF(values, PyList_AsTuple(values));
// Success:
done:
Py_DECREF(get);