Skip to content

Commit 0342097

Browse files
committed
fix vector call opt
1 parent 9d22a53 commit 0342097

7 files changed

Lines changed: 63 additions & 7 deletions

File tree

‎Lib/test/test_capi/test_opt.py‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3300,6 +3300,26 @@ def testfunc(n):
33003300
self.assertIn("_CALL_BUILTIN_CLASS", uops)
33013301
self.assertNotIn("_GUARD_CALLABLE_BUILTIN_CLASS", uops)
33023302

3303+
def test_call_builtin_class_custom_metaclass(self):
3304+
_testcapi = import_helper.import_module("_testcapi")
3305+
3306+
def testfunc(cls, n):
3307+
for _ in range(n):
3308+
result = cls()
3309+
return result
3310+
3311+
Meta = _testcapi.make_vectorcall_class(type)
3312+
C = type.__new__(Meta, "C", (), {})
3313+
Meta.set_vectorcall(C, type)
3314+
3315+
testfunc(list, TIER2_THRESHOLD)
3316+
ex = get_first_executor(testfunc)
3317+
self.assertIsNotNone(ex)
3318+
uops = get_opnames(ex)
3319+
self.assertIn("_GUARD_CALLABLE_BUILTIN_CLASS", uops)
3320+
self.assertIn("_CALL_BUILTIN_CLASS", uops)
3321+
self.assertEqual(testfunc(C, 16), "tp_call")
3322+
33033323
def test_call_builtin_o(self):
33043324
def testfunc(n):
33053325
x = 0

‎Lib/test/test_opcache.py‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,42 @@ def __init__(self, arg):
497497

498498

499499
class TestCallCache(TestBase):
500+
@requires_jit_disabled
501+
@requires_specialization
502+
def test_call_builtin_class_custom_metaclass(self):
503+
_testcapi = import_module("_testcapi")
504+
505+
def call(cls):
506+
return cls()
507+
508+
Meta = _testcapi.make_vectorcall_class(type)
509+
C = type.__new__(Meta, "C", (), {})
510+
Meta.set_vectorcall(C, type)
511+
512+
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
513+
call(list)
514+
self.assert_specialized(call, "CALL_BUILTIN_CLASS")
515+
Meta.__call__ = lambda cls: "custom"
516+
self.assertEqual(call(C), "custom")
517+
518+
@requires_jit_disabled
519+
@requires_specialization
520+
def test_call_immutable_class_custom_metaclass(self):
521+
_testcapi = import_module("_testcapi")
522+
_testlimitedcapi = import_module("_testlimitedcapi")
523+
524+
def call(cls):
525+
return cls()
526+
527+
Meta = _testcapi.make_vectorcall_class(type)
528+
C = type.__new__(Meta, "C", (), {})
529+
Meta.set_vectorcall(C, type)
530+
_testlimitedcapi.type_freeze(C)
531+
532+
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
533+
self.assertEqual(call(C), "tp_call")
534+
self.assert_specialized(call, "CALL_NON_PY_GENERAL")
535+
500536
def test_too_many_defaults_0(self):
501537
def f():
502538
pass

‎Modules/_testinternalcapi/test_cases.c.h‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Python/bytecodes.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4794,7 +4794,7 @@ dummy_func(
47944794

47954795
op(_GUARD_CALLABLE_BUILTIN_CLASS, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) {
47964796
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
4797-
EXIT_IF(!PyType_Check(callable_o));
4797+
EXIT_IF(!Py_IS_TYPE(callable_o, &PyType_Type));
47984798
PyTypeObject *tp = (PyTypeObject *)callable_o;
47994799
EXIT_IF(tp->tp_vectorcall == NULL);
48004800
}

‎Python/executor_cases.c.h‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Python/generated_cases.c.h‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Python/specialize.c‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,6 +1659,9 @@ specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
16591659
{
16601660
assert(PyType_Check(callable));
16611661
PyTypeObject *tp = _PyType_CAST(callable);
1662+
if (Py_TYPE(tp) != &PyType_Type) {
1663+
goto generic;
1664+
}
16621665
if (tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
16631666
int oparg = instr->op.arg;
16641667
if (nargs == 1 && oparg == 1) {
@@ -1681,9 +1684,6 @@ specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
16811684
}
16821685
goto generic;
16831686
}
1684-
if (Py_TYPE(tp) != &PyType_Type) {
1685-
goto generic;
1686-
}
16871687
if (tp->tp_new == PyBaseObject_Type.tp_new) {
16881688
unsigned int tp_version = 0;
16891689
PyObject *init = get_init_for_simple_managed_python_class(tp, &tp_version);

0 commit comments

Comments
 (0)