154 lines
3.1 KiB
Plaintext
154 lines
3.1 KiB
Plaintext
|
-- 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
|