https://github.com/python/cpython/commit/e66d0399cc2e78fcdb6a0113cd757d2ce567ca7c
commit: e66d0399cc2e78fcdb6a0113cd757d2ce567ca7c
branch: main
author: Mark Shannon <[email protected]>
committer: markshannon <[email protected]>
date: 2024-02-01T19:39:32Z
summary:
GH-114806. Don't specialize calls to classes with metaclasses. (GH-114870)
files:
A Misc/NEWS.d/next/Core and
Builtins/2024-02-01-18-16-52.gh-issue-114806.wrH2J6.rst
M Lib/test/test_class.py
M Python/specialize.c
diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py
index 1531aad4f1f779..d59271435e9eb0 100644
--- a/Lib/test/test_class.py
+++ b/Lib/test/test_class.py
@@ -771,6 +771,22 @@ def add_one_level():
with self.assertRaises(RecursionError):
add_one_level()
+ def testMetaclassCallOptimization(self):
+ calls = 0
+
+ class TypeMetaclass(type):
+ def __call__(cls, *args, **kwargs):
+ nonlocal calls
+ calls += 1
+ return type.__call__(cls, *args, **kwargs)
+
+ class Type(metaclass=TypeMetaclass):
+ def __init__(self, obj):
+ self._obj = obj
+
+ for i in range(100):
+ Type(i)
+ self.assertEqual(calls, 100)
if __name__ == '__main__':
unittest.main()
diff --git a/Misc/NEWS.d/next/Core and
Builtins/2024-02-01-18-16-52.gh-issue-114806.wrH2J6.rst b/Misc/NEWS.d/next/Core
and Builtins/2024-02-01-18-16-52.gh-issue-114806.wrH2J6.rst
new file mode 100644
index 00000000000000..795f2529df8207
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and
Builtins/2024-02-01-18-16-52.gh-issue-114806.wrH2J6.rst
@@ -0,0 +1,3 @@
+No longer specialize calls to classes, if those classes have metaclasses.
+Fixes bug where the ``__call__`` method of the metaclass was not being
+called.
diff --git a/Python/specialize.c b/Python/specialize.c
index a9efbe0453b94e..e38e3556a6d642 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -540,6 +540,7 @@ _PyCode_Quicken(PyCodeObject *code)
#define SPEC_FAIL_CALL_METHOD_WRAPPER 28
#define SPEC_FAIL_CALL_OPERATOR_WRAPPER 29
#define SPEC_FAIL_CALL_INIT_NOT_SIMPLE 30
+#define SPEC_FAIL_CALL_METACLASS 31
/* COMPARE_OP */
#define SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES 12
@@ -1757,6 +1758,10 @@ specialize_class_call(PyObject *callable, _Py_CODEUNIT
*instr, int nargs)
SPEC_FAIL_CALL_STR : SPEC_FAIL_CALL_CLASS_NO_VECTORCALL);
return -1;
}
+ if (Py_TYPE(tp) != &PyType_Type) {
+ SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_METACLASS);
+ return -1;
+ }
if (tp->tp_new == PyBaseObject_Type.tp_new) {
PyFunctionObject *init = get_init_for_simple_managed_python_class(tp);
if (type_get_version(tp, CALL) == 0) {
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]