Skip to content

Commit 98eee40

Browse files
authored
[mypyc] Implement dict clear primitive (#9724)
Implements dict clear primitive for improved performance. Related ticket: mypyc/mypyc#644
1 parent 88f76ee commit 98eee40

File tree

5 files changed

+47
-0
lines changed

5 files changed

+47
-0
lines changed

mypyc/lib-rt/CPy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ PyObject *CPyDict_ItemsView(PyObject *dict);
348348
PyObject *CPyDict_Keys(PyObject *dict);
349349
PyObject *CPyDict_Values(PyObject *dict);
350350
PyObject *CPyDict_Items(PyObject *dict);
351+
char CPyDict_Clear(PyObject *dict);
351352
PyObject *CPyDict_GetKeysIter(PyObject *dict);
352353
PyObject *CPyDict_GetItemsIter(PyObject *dict);
353354
PyObject *CPyDict_GetValuesIter(PyObject *dict);

mypyc/lib-rt/dict_ops.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,18 @@ PyObject *CPyDict_Items(PyObject *dict) {
226226
return list;
227227
}
228228

229+
char CPyDict_Clear(PyObject *dict) {
230+
if (PyDict_CheckExact(dict)) {
231+
PyDict_Clear(dict);
232+
} else {
233+
PyObject *res = PyObject_CallMethod(dict, "clear", NULL);
234+
if (res == NULL) {
235+
return 0;
236+
}
237+
}
238+
return 1;
239+
}
240+
229241
PyObject *CPyDict_GetKeysIter(PyObject *dict) {
230242
if (PyDict_CheckExact(dict)) {
231243
// Return dict itself to indicate we can use fast path instead.

mypyc/primitives/dict_ops.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,14 @@
142142
c_function_name='CPyDict_ItemsView',
143143
error_kind=ERR_MAGIC)
144144

145+
# dict.clear()
146+
method_op(
147+
name='clear',
148+
arg_types=[dict_rprimitive],
149+
return_type=bit_rprimitive,
150+
c_function_name='CPyDict_Clear',
151+
error_kind=ERR_FALSE)
152+
145153
# list(dict.keys())
146154
dict_keys_op = custom_op(
147155
arg_types=[dict_rprimitive],

mypyc/test-data/irbuild-dict.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,3 +312,15 @@ L0:
312312
r0 = load_address PyDict_Type
313313
x = r0
314314
return 1
315+
316+
[case testDictClear]
317+
from typing import Dict
318+
def f(d: Dict[int, int]) -> None:
319+
return d.clear()
320+
[out]
321+
def f(d):
322+
d :: dict
323+
r0 :: bit
324+
L0:
325+
r0 = CPyDict_Clear(d)
326+
return 1

mypyc/test-data/run-dicts.test

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ od.move_to_end(1)
9191
assert get_content(od) == ([3, 1], [4, 2], [(3, 4), (1, 2)])
9292
assert get_content_set({1: 2}) == ({1}, {2}, {(1, 2)})
9393
assert get_content_set(od) == ({1, 3}, {2, 4}, {(1, 2), (3, 4)})
94+
9495
[typing fixtures/typing-full.pyi]
9596

9697
[case testDictIterationMethodsRun]
@@ -192,3 +193,16 @@ else:
192193
2
193194
4
194195
2
196+
197+
[case testDictMethods]
198+
from collections import defaultdict
199+
from typing import Dict
200+
201+
def test_dict_clear() -> None:
202+
d = {'a': 1, 'b': 2}
203+
d.clear()
204+
assert d == {}
205+
dd: Dict[str, int] = defaultdict(int)
206+
dd['a'] = 1
207+
dd.clear()
208+
assert dd == {}

0 commit comments

Comments
 (0)