Skip to content

Commit 766c43c

Browse files
[mypyc] feat: exact_dict_set_item_op (#19657)
This PR implements a `exact_dict_set_item_op` custom_op in preparation for the addition of exact_dict_rprimitive. We don't actually need to implement exact_dict_rprimitive before implementing this op as long as we accept that it will not be used for CallExpr specialization. This is okay for us now, as it is already addressed in the larger PR.
1 parent 27b9ba0 commit 766c43c

File tree

8 files changed

+40
-25
lines changed

8 files changed

+40
-25
lines changed

mypyc/irbuild/classdef.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
)
6767
from mypyc.irbuild.prepare import GENERATOR_HELPER_NAME
6868
from mypyc.irbuild.util import dataclass_type, get_func_def, is_constant, is_dataclass_decorator
69-
from mypyc.primitives.dict_ops import dict_new_op, dict_set_item_op
69+
from mypyc.primitives.dict_ops import dict_new_op, exact_dict_set_item_op
7070
from mypyc.primitives.generic_ops import (
7171
iter_op,
7272
next_op,
@@ -271,8 +271,8 @@ def finalize(self, ir: ClassIR) -> None:
271271
)
272272

273273
# Add the non-extension class to the dict
274-
self.builder.primitive_op(
275-
dict_set_item_op,
274+
self.builder.call_c(
275+
exact_dict_set_item_op,
276276
[
277277
self.builder.load_globals_dict(),
278278
self.builder.load_str(self.cdef.name),
@@ -487,8 +487,10 @@ def allocate_class(builder: IRBuilder, cdef: ClassDef) -> Value:
487487
builder.add(InitStatic(tp, cdef.name, builder.module_name, NAMESPACE_TYPE))
488488

489489
# Add it to the dict
490-
builder.primitive_op(
491-
dict_set_item_op, [builder.load_globals_dict(), builder.load_str(cdef.name), tp], cdef.line
490+
builder.call_c(
491+
exact_dict_set_item_op,
492+
[builder.load_globals_dict(), builder.load_str(cdef.name), tp],
493+
cdef.line,
492494
)
493495

494496
return tp
@@ -672,7 +674,7 @@ def add_non_ext_class_attr_ann(
672674
typ = builder.add(LoadAddress(type_object_op.type, type_object_op.src, stmt.line))
673675

674676
key = builder.load_str(lvalue.name)
675-
builder.primitive_op(dict_set_item_op, [non_ext.anns, key, typ], stmt.line)
677+
builder.call_c(exact_dict_set_item_op, [non_ext.anns, key, typ], stmt.line)
676678

677679

678680
def add_non_ext_class_attr(

mypyc/irbuild/expression.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@
9797
)
9898
from mypyc.irbuild.specialize import apply_function_specialization, apply_method_specialization
9999
from mypyc.primitives.bytes_ops import bytes_slice_op
100-
from mypyc.primitives.dict_ops import dict_get_item_op, dict_new_op, dict_set_item_op
100+
from mypyc.primitives.dict_ops import dict_get_item_op, dict_new_op, exact_dict_set_item_op
101101
from mypyc.primitives.generic_ops import iter_op
102102
from mypyc.primitives.list_ops import list_append_op, list_extend_op, list_slice_op
103103
from mypyc.primitives.misc_ops import ellipsis_op, get_module_dict_op, new_slice_op, type_op
@@ -1030,7 +1030,7 @@ def transform_dictionary_comprehension(builder: IRBuilder, o: DictionaryComprehe
10301030
def gen_inner_stmts() -> None:
10311031
k = builder.accept(o.key)
10321032
v = builder.accept(o.value)
1033-
builder.primitive_op(dict_set_item_op, [builder.read(d), k, v], o.line)
1033+
builder.call_c(exact_dict_set_item_op, [builder.read(d), k, v], o.line)
10341034

10351035
comprehension_helper(builder, loop_params, gen_inner_stmts, o.line)
10361036
return builder.read(d)

mypyc/irbuild/function.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,11 @@
7676
)
7777
from mypyc.irbuild.generator import gen_generator_func, gen_generator_func_body
7878
from mypyc.irbuild.targets import AssignmentTarget
79-
from mypyc.primitives.dict_ops import dict_get_method_with_none, dict_new_op, dict_set_item_op
79+
from mypyc.primitives.dict_ops import (
80+
dict_get_method_with_none,
81+
dict_new_op,
82+
exact_dict_set_item_op,
83+
)
8084
from mypyc.primitives.generic_ops import py_setattr_op
8185
from mypyc.primitives.misc_ops import register_function
8286
from mypyc.primitives.registry import builtin_names
@@ -123,8 +127,8 @@ def transform_decorator(builder: IRBuilder, dec: Decorator) -> None:
123127

124128
if decorated_func is not None:
125129
# Set the callable object representing the decorated function as a global.
126-
builder.primitive_op(
127-
dict_set_item_op,
130+
builder.call_c(
131+
exact_dict_set_item_op,
128132
[builder.load_globals_dict(), builder.load_str(dec.func.name), decorated_func],
129133
decorated_func.line,
130134
)
@@ -826,7 +830,7 @@ def generate_singledispatch_dispatch_function(
826830
find_impl = builder.load_module_attr_by_fullname("functools._find_impl", line)
827831
registry = load_singledispatch_registry(builder, dispatch_func_obj, line)
828832
uncached_impl = builder.py_call(find_impl, [arg_type, registry], line)
829-
builder.primitive_op(dict_set_item_op, [dispatch_cache, arg_type, uncached_impl], line)
833+
builder.call_c(exact_dict_set_item_op, [dispatch_cache, arg_type, uncached_impl], line)
830834
builder.assign(impl_to_use, uncached_impl, line)
831835
builder.goto(call_func)
832836

@@ -1003,7 +1007,7 @@ def maybe_insert_into_registry_dict(builder: IRBuilder, fitem: FuncDef) -> None:
10031007
registry = load_singledispatch_registry(builder, dispatch_func_obj, line)
10041008
for typ in types:
10051009
loaded_type = load_type(builder, typ, None, line)
1006-
builder.primitive_op(dict_set_item_op, [registry, loaded_type, to_insert], line)
1010+
builder.call_c(exact_dict_set_item_op, [registry, loaded_type, to_insert], line)
10071011
dispatch_cache = builder.builder.get_attr(
10081012
dispatch_func_obj, "dispatch_cache", dict_rprimitive, line
10091013
)

mypyc/primitives/dict_ops.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,15 @@
9898
error_kind=ERR_NEG_INT,
9999
)
100100

101+
# dict[key] = value (exact dict only, no subclasses)
102+
# NOTE: this is currently for internal use only, and not used for CallExpr specialization
103+
exact_dict_set_item_op = custom_op(
104+
arg_types=[dict_rprimitive, object_rprimitive, object_rprimitive],
105+
return_type=c_int_rprimitive,
106+
c_function_name="PyDict_SetItem",
107+
error_kind=ERR_NEG_INT,
108+
)
109+
101110
# key in dict
102111
binary_op(
103112
name="in",

mypyc/test-data/irbuild-basic.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1993,7 +1993,7 @@ L6:
19931993
r13 = CPyTagged_Multiply(x, x)
19941994
r14 = box(int, x)
19951995
r15 = box(int, r13)
1996-
r16 = CPyDict_SetItem(r0, r14, r15)
1996+
r16 = PyDict_SetItem(r0, r14, r15)
19971997
r17 = r16 >= 0 :: signed
19981998
L7:
19991999
r18 = r6 + 1
@@ -2620,7 +2620,7 @@ L0:
26202620
d = r14
26212621
r15 = __main__.globals :: static
26222622
r16 = 'd'
2623-
r17 = CPyDict_SetItem(r15, r16, r14)
2623+
r17 = PyDict_SetItem(r15, r16, r14)
26242624
r18 = r17 >= 0 :: signed
26252625
r19 = 'c'
26262626
r20 = builtins :: module
@@ -2693,7 +2693,7 @@ L2:
26932693
keep_alive r17
26942694
r24 = __main__.globals :: static
26952695
r25 = 'c'
2696-
r26 = CPyDict_SetItem(r24, r25, r23)
2696+
r26 = PyDict_SetItem(r24, r25, r23)
26972697
r27 = r26 >= 0 :: signed
26982698
return 1
26992699

mypyc/test-data/irbuild-classes.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ L2:
303303
__main__.C = r27 :: type
304304
r33 = __main__.globals :: static
305305
r34 = 'C'
306-
r35 = CPyDict_SetItem(r33, r34, r27)
306+
r35 = PyDict_SetItem(r33, r34, r27)
307307
r36 = r35 >= 0 :: signed
308308
r37 = <error> :: object
309309
r38 = '__main__'
@@ -316,7 +316,7 @@ L2:
316316
__main__.S = r40 :: type
317317
r45 = __main__.globals :: static
318318
r46 = 'S'
319-
r47 = CPyDict_SetItem(r45, r46, r40)
319+
r47 = PyDict_SetItem(r45, r46, r40)
320320
r48 = r47 >= 0 :: signed
321321
r49 = __main__.C :: type
322322
r50 = __main__.S :: type
@@ -340,7 +340,7 @@ L2:
340340
__main__.D = r61 :: type
341341
r68 = __main__.globals :: static
342342
r69 = 'D'
343-
r70 = CPyDict_SetItem(r68, r69, r61)
343+
r70 = PyDict_SetItem(r68, r69, r61)
344344
r71 = r70 >= 0 :: signed
345345
return 1
346346

mypyc/test-data/irbuild-generics.test

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ L17:
351351
k = r49
352352
v = r50
353353
r51 = box(int, v)
354-
r52 = CPyDict_SetItem(r40, k, r51)
354+
r52 = PyDict_SetItem(r40, k, r51)
355355
r53 = r52 >= 0 :: signed
356356
L18:
357357
r54 = CPyDict_CheckSize(m, r42)
@@ -493,7 +493,7 @@ L17:
493493
r49 = cast(union[int, str], r47)
494494
k = r48
495495
v = r49
496-
r50 = CPyDict_SetItem(r39, k, v)
496+
r50 = PyDict_SetItem(r39, k, v)
497497
r51 = r50 >= 0 :: signed
498498
L18:
499499
r52 = CPyDict_CheckSize(m, r41)
@@ -630,7 +630,7 @@ L17:
630630
r47 = cast(str, r45)
631631
k = r47
632632
v = r46
633-
r48 = CPyDict_SetItem(r38, k, v)
633+
r48 = PyDict_SetItem(r38, k, v)
634634
r49 = r48 >= 0 :: signed
635635
L18:
636636
r50 = CPyDict_CheckSize(t, r40)
@@ -742,7 +742,7 @@ L6:
742742
r17 = cast(str, r15)
743743
k = r17
744744
v = r16
745-
r18 = CPyDict_SetItem(r8, k, v)
745+
r18 = PyDict_SetItem(r8, k, v)
746746
r19 = r18 >= 0 :: signed
747747
L7:
748748
r20 = CPyDict_CheckSize(kwargs, r10)

mypyc/test-data/irbuild-singledispatch.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ L2:
7676
r12 = load_address r11
7777
r13 = PyObject_Vectorcall(r9, r12, 2, 0)
7878
keep_alive r1, r10
79-
r14 = CPyDict_SetItem(r2, r1, r13)
79+
r14 = PyDict_SetItem(r2, r1, r13)
8080
r15 = r14 >= 0 :: signed
8181
r6 = r13
8282
L3:
@@ -214,7 +214,7 @@ L2:
214214
r12 = load_address r11
215215
r13 = PyObject_Vectorcall(r9, r12, 2, 0)
216216
keep_alive r1, r10
217-
r14 = CPyDict_SetItem(r2, r1, r13)
217+
r14 = PyDict_SetItem(r2, r1, r13)
218218
r15 = r14 >= 0 :: signed
219219
r6 = r13
220220
L3:

0 commit comments

Comments
 (0)