| -- Test cases for calls using the vectorcall API (Python 3.8+) |
| -- |
| -- Vectorcalls are faster than the legacy API, especially with keyword arguments, |
| -- since there is no need to allocate a temporary dictionary for keyword args. |
| |
| [case testeVectorcallBasic_python3_8] |
| from typing import Any |
| |
| def f(c: Any) -> None: |
| c() |
| c('x', 'y') |
| [out] |
| def f(c): |
| c, r0 :: object |
| r1, r2 :: str |
| r3 :: object[2] |
| r4 :: object_ptr |
| r5 :: object |
| L0: |
| r0 = _PyObject_Vectorcall(c, 0, 0, 0) |
| r1 = 'x' |
| r2 = 'y' |
| r3 = [r1, r2] |
| r4 = load_address r3 |
| r5 = _PyObject_Vectorcall(c, r4, 2, 0) |
| keep_alive r1, r2 |
| return 1 |
| |
| [case testVectorcallKeywords_python3_8] |
| from typing import Any |
| |
| def f(c: Any) -> None: |
| c(x='a') |
| c('x', a='y', b='z') |
| [out] |
| def f(c): |
| c :: object |
| r0 :: str |
| r1 :: object[1] |
| r2 :: object_ptr |
| r3, r4 :: object |
| r5, r6, r7 :: str |
| r8 :: object[3] |
| r9 :: object_ptr |
| r10, r11 :: object |
| L0: |
| r0 = 'a' |
| r1 = [r0] |
| r2 = load_address r1 |
| r3 = ('x',) |
| r4 = _PyObject_Vectorcall(c, r2, 0, r3) |
| keep_alive r0 |
| r5 = 'x' |
| r6 = 'y' |
| r7 = 'z' |
| r8 = [r5, r6, r7] |
| r9 = load_address r8 |
| r10 = ('a', 'b') |
| r11 = _PyObject_Vectorcall(c, r9, 1, r10) |
| keep_alive r5, r6, r7 |
| return 1 |
| |
| [case testVectorcallMethod_python3_8] |
| from typing import Any |
| |
| def f(o: Any) -> None: |
| # On Python 3.8 vectorcalls are only faster with keyword args |
| o.m('x') |
| o.m('x', a='y') |
| [out] |
| def f(o): |
| o :: object |
| r0, r1 :: str |
| r2 :: object |
| r3, r4, r5 :: str |
| r6 :: object |
| r7 :: object[2] |
| r8 :: object_ptr |
| r9, r10 :: object |
| L0: |
| r0 = 'x' |
| r1 = 'm' |
| r2 = CPyObject_CallMethodObjArgs(o, r1, r0, 0) |
| r3 = 'x' |
| r4 = 'y' |
| r5 = 'm' |
| r6 = CPyObject_GetAttr(o, r5) |
| r7 = [r3, r4] |
| r8 = load_address r7 |
| r9 = ('a',) |
| r10 = _PyObject_Vectorcall(r6, r8, 1, r9) |
| keep_alive r3, r4 |
| return 1 |
| |
| [case testVectorcallMethod_python3_9_64bit] |
| from typing import Any |
| |
| def f(o: Any) -> None: |
| # Python 3.9 has a new API for calling methods |
| o.m('x') |
| o.m('x', 'y', a='z') |
| [out] |
| def f(o): |
| o :: object |
| r0, r1 :: str |
| r2 :: object[2] |
| r3 :: object_ptr |
| r4 :: object |
| r5, r6, r7, r8 :: str |
| r9 :: object[4] |
| r10 :: object_ptr |
| r11, r12 :: object |
| L0: |
| r0 = 'x' |
| r1 = 'm' |
| r2 = [o, r0] |
| r3 = load_address r2 |
| r4 = PyObject_VectorcallMethod(r1, r3, 9223372036854775810, 0) |
| keep_alive o, r0 |
| r5 = 'x' |
| r6 = 'y' |
| r7 = 'z' |
| r8 = 'm' |
| r9 = [o, r5, r6, r7] |
| r10 = load_address r9 |
| r11 = ('a',) |
| r12 = PyObject_VectorcallMethod(r8, r10, 9223372036854775811, r11) |
| keep_alive o, r5, r6, r7 |
| return 1 |
| |
| [case testVectorcallMethod_python3_9_32bit] |
| from typing import Any |
| |
| def f(o: Any) -> None: |
| # The IR is slightly different on 32-bit platforms |
| o.m('x', a='y') |
| [out] |
| def f(o): |
| o :: object |
| r0, r1, r2 :: str |
| r3 :: object[3] |
| r4 :: object_ptr |
| r5, r6 :: object |
| L0: |
| r0 = 'x' |
| r1 = 'y' |
| r2 = 'm' |
| r3 = [o, r0, r1] |
| r4 = load_address r3 |
| r5 = ('a',) |
| r6 = PyObject_VectorcallMethod(r2, r4, 2147483650, r5) |
| keep_alive o, r0, r1 |
| return 1 |