Skip to content

Commit 2be0326

Browse files
committed
fix: separate fastpath for dict vs nondict
1 parent 82e39c4 commit 2be0326

File tree

2 files changed

+33
-34
lines changed

2 files changed

+33
-34
lines changed

mypyc/irbuild/ll_builder.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
from mypyc.primitives.bytes_ops import bytes_compare
128128
from mypyc.primitives.dict_ops import (
129129
dict_build_op,
130+
dict_copy,
130131
dict_copy_op,
131132
dict_new_op,
132133
dict_ssize_t_size_op,
@@ -805,16 +806,21 @@ def _construct_varargs(
805806
return value, self._create_dict([], [], line)
806807
elif len(args) == 2 and args[1][1] == ARG_STAR2:
807808
# fn(*args, **kwargs)
809+
# TODO: extend to cover(*args, **k, **w, **a, **r, **g, **s)
808810
if is_tuple_rprimitive(value.type):
809811
star_result = value
810812
elif is_list_rprimitive(value.type):
811813
star_result = self.primitive_op(list_tuple_op, [value], line)
812814
else:
813815
star_result = self.primitive_op(sequence_tuple_op, [value], line)
814-
if is_dict_rprimitive(args[1][0].type):
815-
# even faster fastpath for decorators
816-
return star_result, self.primitive_op(dict_copy_op, [args[1][0]], line)
817-
continue
816+
817+
star2_arg = args[1]
818+
star2_value = star2_arg[0]
819+
if is_dict_rprimitive(star2_value.type):
820+
star2_fastpath_op = dict_copy_op
821+
else:
822+
star2_fastpath_op = dict_copy
823+
return star_result, self.primitive_op(star2_fastpath_op, [star2_value], line)
818824
# elif ...: TODO extend this to optimize fn(*args, k=1, **kwargs) case
819825
# TODO optimize this case using the length utils - currently in review
820826
star_result = self.new_list_op(star_values, line)
@@ -824,7 +830,11 @@ def _construct_varargs(
824830
if len(args) == 1:
825831
# early exit with fastpath if the only arg is ARG_STAR2
826832
# TODO: can we maintain an empty tuple in memory and just reuse it again and again?
827-
return self.new_tuple([], line), self.primitive_op(dict_copy_op, [args[0][0]], line)
833+
if is_dict_rprimitive(value.type):
834+
star2_fastpath_op = dict_copy_op
835+
else:
836+
star2_fastpath_op = dict_copy
837+
return self.new_tuple([], line), self.primitive_op(star2_fastpath_op, [args[0][0]], line)
828838

829839
star2_result = self._create_dict(star2_keys, star2_values, line)
830840

mypyc/test-data/irbuild-basic.test

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,12 +1742,10 @@ def g():
17421742
r6, r7 :: dict
17431743
r8 :: str
17441744
r9 :: object
1745-
r10 :: dict
1746-
r11 :: i32
1747-
r12 :: bit
1748-
r13 :: tuple
1749-
r14 :: object
1750-
r15 :: tuple[int, int, int]
1745+
r10 :: tuple
1746+
r11 :: dict
1747+
r12 :: object
1748+
r13 :: tuple[int, int, int]
17511749
L0:
17521750
r0 = 'a'
17531751
r1 = 'b'
@@ -1759,13 +1757,11 @@ L0:
17591757
r7 = __main__.globals :: static
17601758
r8 = 'f'
17611759
r9 = CPyDict_GetItem(r7, r8)
1762-
r10 = PyDict_New()
1763-
r11 = CPyDict_UpdateInDisplay(r10, r6)
1764-
r12 = r11 >= 0 :: signed
1765-
r13 = PyTuple_Pack(0)
1766-
r14 = PyObject_Call(r9, r13, r10)
1767-
r15 = unbox(tuple[int, int, int], r14)
1768-
return r15
1760+
r10 = PyTuple_Pack(0)
1761+
r11 = PyDict_Copy(r6)
1762+
r12 = PyObject_Call(r9, r10, r11)
1763+
r13 = unbox(tuple[int, int, int], r12)
1764+
return r13
17691765
def h():
17701766
r0, r1 :: str
17711767
r2, r3 :: object
@@ -3672,18 +3668,14 @@ def wrapper_deco_obj.__call__(__mypyc_self__, lst, kwargs):
36723668
r1 :: object
36733669
r2 :: tuple
36743670
r3 :: dict
3675-
r4 :: i32
3676-
r5 :: bit
3677-
r6 :: object
3671+
r4 :: object
36783672
L0:
36793673
r0 = __mypyc_self__.__mypyc_env__
36803674
r1 = r0.fn
36813675
r2 = PyList_AsTuple(lst)
3682-
r3 = PyDict_New()
3683-
r4 = CPyDict_UpdateInDisplay(r3, kwargs)
3684-
r5 = r4 >= 0 :: signed
3685-
r6 = PyObject_Call(r1, r2, r3)
3686-
return r6
3676+
r3 = PyDict_Copy(kwargs)
3677+
r4 = PyObject_Call(r1, r2, r3)
3678+
return r4
36873679
def deco(fn):
36883680
fn :: object
36893681
r0 :: __main__.deco_env
@@ -3779,18 +3771,14 @@ def wrapper_deco_obj.__call__(__mypyc_self__, args, kwargs):
37793771
r1 :: object
37803772
r2 :: tuple
37813773
r3 :: dict
3782-
r4 :: i32
3783-
r5 :: bit
3784-
r6 :: object
3774+
r4 :: object
37853775
L0:
37863776
r0 = __mypyc_self__.__mypyc_env__
37873777
r1 = r0.fn
37883778
r2 = PySequence_Tuple(args)
3789-
r3 = PyDict_New()
3790-
r4 = CPyDict_UpdateInDisplay(r3, kwargs)
3791-
r5 = r4 >= 0 :: signed
3792-
r6 = PyObject_Call(r1, r2, r3)
3793-
return r6
3779+
r3 = PyDict_Copy(kwargs)
3780+
r4 = PyObject_Call(r1, r2, r3)
3781+
return r4
37943782
def deco(fn):
37953783
fn :: object
37963784
r0 :: __main__.deco_env
@@ -3805,3 +3793,4 @@ L0:
38053793
r2.__mypyc_env__ = r0; r3 = is_error
38063794
wrapper = r2
38073795
return wrapper
3796+

0 commit comments

Comments
 (0)