GH-114806. Don't specialize calls to classes with metaclasses. (GH-114870)

This commit is contained in:
Mark Shannon 2024-02-01 19:39:32 +00:00 committed by GitHub
parent 97cc58f977
commit e66d0399cc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 24 additions and 0 deletions

View file

@ -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()

View file

@ -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.

View file

@ -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) {