Skip to content

Commit

Permalink
[mypyc] Implement dict clear primitive (#9724)
Browse files Browse the repository at this point in the history
Implements dict clear primitive for improved performance.

Related ticket: mypyc/mypyc#644
  • Loading branch information
vsakkas authored Dec 2, 2020
1 parent 88f76ee commit 98eee40
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 0 deletions.
1 change: 1 addition & 0 deletions mypyc/lib-rt/CPy.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ PyObject *CPyDict_ItemsView(PyObject *dict);
PyObject *CPyDict_Keys(PyObject *dict);
PyObject *CPyDict_Values(PyObject *dict);
PyObject *CPyDict_Items(PyObject *dict);
char CPyDict_Clear(PyObject *dict);
PyObject *CPyDict_GetKeysIter(PyObject *dict);
PyObject *CPyDict_GetItemsIter(PyObject *dict);
PyObject *CPyDict_GetValuesIter(PyObject *dict);
Expand Down
12 changes: 12 additions & 0 deletions mypyc/lib-rt/dict_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,18 @@ PyObject *CPyDict_Items(PyObject *dict) {
return list;
}

char CPyDict_Clear(PyObject *dict) {
if (PyDict_CheckExact(dict)) {
PyDict_Clear(dict);
} else {
PyObject *res = PyObject_CallMethod(dict, "clear", NULL);
if (res == NULL) {
return 0;
}
}
return 1;
}

PyObject *CPyDict_GetKeysIter(PyObject *dict) {
if (PyDict_CheckExact(dict)) {
// Return dict itself to indicate we can use fast path instead.
Expand Down
8 changes: 8 additions & 0 deletions mypyc/primitives/dict_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@
c_function_name='CPyDict_ItemsView',
error_kind=ERR_MAGIC)

# dict.clear()
method_op(
name='clear',
arg_types=[dict_rprimitive],
return_type=bit_rprimitive,
c_function_name='CPyDict_Clear',
error_kind=ERR_FALSE)

# list(dict.keys())
dict_keys_op = custom_op(
arg_types=[dict_rprimitive],
Expand Down
12 changes: 12 additions & 0 deletions mypyc/test-data/irbuild-dict.test
Original file line number Diff line number Diff line change
Expand Up @@ -312,3 +312,15 @@ L0:
r0 = load_address PyDict_Type
x = r0
return 1

[case testDictClear]
from typing import Dict
def f(d: Dict[int, int]) -> None:
return d.clear()
[out]
def f(d):
d :: dict
r0 :: bit
L0:
r0 = CPyDict_Clear(d)
return 1
14 changes: 14 additions & 0 deletions mypyc/test-data/run-dicts.test
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ od.move_to_end(1)
assert get_content(od) == ([3, 1], [4, 2], [(3, 4), (1, 2)])
assert get_content_set({1: 2}) == ({1}, {2}, {(1, 2)})
assert get_content_set(od) == ({1, 3}, {2, 4}, {(1, 2), (3, 4)})

[typing fixtures/typing-full.pyi]

[case testDictIterationMethodsRun]
Expand Down Expand Up @@ -192,3 +193,16 @@ else:
2
4
2

[case testDictMethods]
from collections import defaultdict
from typing import Dict

def test_dict_clear() -> None:
d = {'a': 1, 'b': 2}
d.clear()
assert d == {}
dd: Dict[str, int] = defaultdict(int)
dd['a'] = 1
dd.clear()
assert dd == {}

0 comments on commit 98eee40

Please sign in to comment.