Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8efdebb

Browse files
committed
dict stuff
1 parent 00d06c2 commit 8efdebb

14 files changed

+517
-489
lines changed

mypyc/irbuild/builder.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@
9292
RUnion,
9393
bitmap_rprimitive,
9494
c_pyssize_t_rprimitive,
95-
dict_rprimitive,
9695
int_rprimitive,
9796
is_float_rprimitive,
9897
is_list_rprimitive,
@@ -103,6 +102,7 @@
103102
none_rprimitive,
104103
object_rprimitive,
105104
str_rprimitive,
105+
true_dict_rprimitive,
106106
)
107107
from mypyc.irbuild.context import FuncInfo, ImplicitClass
108108
from mypyc.irbuild.ll_builder import LowLevelIRBuilder
@@ -124,7 +124,11 @@
124124
)
125125
from mypyc.irbuild.util import bytes_from_str, is_constant
126126
from mypyc.options import CompilerOptions
127-
from mypyc.primitives.dict_ops import dict_get_item_op, true_dict_set_item_op
127+
from mypyc.primitives.dict_ops import (
128+
dict_get_item_op,
129+
true_dict_get_item_op,
130+
true_dict_set_item_op,
131+
)
128132
from mypyc.primitives.generic_ops import iter_op, next_op, py_setattr_op
129133
from mypyc.primitives.list_ops import list_get_item_unsafe_op, list_pop_last, to_list
130134
from mypyc.primitives.misc_ops import check_unpack_count_op, get_module_dict_op, import_op
@@ -1370,10 +1374,10 @@ def load_global(self, expr: NameExpr) -> Value:
13701374
def load_global_str(self, name: str, line: int) -> Value:
13711375
_globals = self.load_globals_dict()
13721376
reg = self.load_str(name)
1373-
return self.primitive_op(dict_get_item_op, [_globals, reg], line)
1377+
return self.primitive_op(true_dict_get_item_op, [_globals, reg], line)
13741378

13751379
def load_globals_dict(self) -> Value:
1376-
return self.add(LoadStatic(dict_rprimitive, "globals", self.module_name))
1380+
return self.add(LoadStatic(true_dict_rprimitive, "globals", self.module_name))
13771381

13781382
def load_module_attr_by_fullname(self, fullname: str, line: int) -> Value:
13791383
module, _, name = fullname.rpartition(".")

mypyc/irbuild/ll_builder.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
is_short_int_rprimitive,
110110
is_str_rprimitive,
111111
is_tagged,
112+
is_true_dict_rprimitive,
112113
is_tuple_rprimitive,
113114
is_uint8_rprimitive,
114115
list_rprimitive,
@@ -128,6 +129,8 @@
128129
dict_new_op,
129130
dict_ssize_t_size_op,
130131
dict_update_in_display_op,
132+
true_dict_copy_op,
133+
true_dict_update_op,
131134
)
132135
from mypyc.primitives.exc_ops import err_occurred_op, keep_propagating_op
133136
from mypyc.primitives.float_ops import copysign_op, int_to_float_op
@@ -787,8 +790,11 @@ def _construct_varargs(
787790
elif kind == ARG_STAR2:
788791
if star2_result is None:
789792
star2_result = self._create_dict(star2_keys, star2_values, line)
790-
791-
self.call_c(dict_update_in_display_op, [star2_result, value], line=line)
793+
if is_true_dict_rprimitive(value):
794+
op = true_dict_update_op
795+
else:
796+
op = dict_update_in_display_op
797+
self.call_c(op, [star2_result, value], line=line)
792798
else:
793799
nullable = kind.is_optional()
794800
maybe_pos = kind.is_positional() and has_star
@@ -1652,9 +1658,18 @@ def make_dict(self, key_value_pairs: Sequence[DictEntry], line: int) -> Value:
16521658
else:
16531659
# **value
16541660
if result is None:
1661+
if len(key_value_pairs) == 1 and is_true_dict_rprimitive(value):
1662+
# fast path for cases like `my_func(**dict(zip(iterable, other)))` and similar
1663+
return self.call_c(true_dict_copy_op, [value], line=line)
1664+
16551665
result = self._create_dict(keys, values, line)
1656-
1657-
self.call_c(dict_update_in_display_op, [result, value], line=line)
1666+
1667+
if is_true_dict_rprimitive(value):
1668+
op = true_dict_update_op
1669+
else:
1670+
op = dict_update_in_display_op
1671+
1672+
self.call_c(op, [result, value], line=line)
16581673

16591674
if result is None:
16601675
result = self._create_dict(keys, values, line)

mypyc/irbuild/match.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
from mypyc.irbuild.builder import IRBuilder
2323
from mypyc.primitives.dict_ops import (
2424
dict_copy,
25-
dict_del_item,
2625
mapping_has_key,
2726
supports_mapping_protocol,
27+
true_dict_del_item,
2828
)
2929
from mypyc.primitives.generic_ops import generic_ssize_t_len_op
3030
from mypyc.primitives.list_ops import (
@@ -239,7 +239,7 @@ def visit_mapping_pattern(self, pattern: MappingPattern) -> None:
239239
self.builder.assign(target, rest, pattern.rest.line)
240240

241241
for i, key_name in enumerate(keys):
242-
self.builder.call_c(dict_del_item, [rest, key_name], pattern.keys[i].line)
242+
self.builder.call_c(true_dict_del_item, [rest, key_name], pattern.keys[i].line)
243243

244244
self.builder.goto(self.code_block)
245245

mypyc/lib-rt/CPy.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -705,18 +705,12 @@ int CPyMapping_Check(PyObject *obj);
705705

706706
// Unsafe dict operations (assume PyDict_CheckExact(dict) is always true)
707707
PyObject *CPyDict_GetItemUnsafe(PyObject *dict, PyObject *key);
708-
int CPyDict_SetItemUnsafe(PyObject *dict, PyObject *key, PyObject *value);
709-
PyObject *CPyDict_KeysViewUnsafe(PyObject *dict);
710-
PyObject *CPyDict_ValuesViewUnsafe(PyObject *dict);
711-
PyObject *CPyDict_ItemsViewUnsafe(PyObject *dict);
712-
PyObject *CPyDict_KeysUnsafe(PyObject *dict);
713-
PyObject *CPyDict_ValuesUnsafe(PyObject *dict);
714-
PyObject *CPyDict_ItemsUnsafe(PyObject *dict);
715-
char CPyDict_ClearUnsafe(PyObject *dict);
716-
PyObject *CPyDict_CopyUnsafe(PyObject *dict);
717708
PyObject *CPyDict_GetKeysIterUnsafe(PyObject *dict);
718709
PyObject *CPyDict_GetItemsIterUnsafe(PyObject *dict);
719710
PyObject *CPyDict_GetValuesIterUnsafe(PyObject *dict);
711+
PyObject *CPyDict_KeysViewUnsafe(PyObject *dict);
712+
PyObject *CPyDict_ValuesViewUnsafe(PyObject *dict);
713+
PyObject *CPyDict_ItemsViewUnsafe(PyObject *dict);
720714

721715
// Check that dictionary didn't change size during iteration.
722716
static inline char CPyDict_CheckSize(PyObject *dict, Py_ssize_t size) {

mypyc/lib-rt/dict_ops.c

Lines changed: 17 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -326,18 +326,14 @@ PyObject *CPyDict_Copy(PyObject *dict) {
326326

327327
PyObject *CPyDict_GetKeysIter(PyObject *dict) {
328328
if (PyDict_CheckExact(dict)) {
329-
// Return dict itself to indicate we can use fast path instead.
330-
Py_INCREF(dict);
331-
return dict;
329+
return CPyDict_GetKeysIterUnsafe(dict);
332330
}
333331
return PyObject_GetIter(dict);
334332
}
335333

336334
PyObject *CPyDict_GetItemsIter(PyObject *dict) {
337335
if (PyDict_CheckExact(dict)) {
338-
// Return dict itself to indicate we can use fast path instead.
339-
Py_INCREF(dict);
340-
return dict;
336+
return CPyDict_GetItemsIterUnsafe(dict);
341337
}
342338
_Py_IDENTIFIER(items);
343339
PyObject *name = _PyUnicode_FromId(&PyId_items); /* borrowed */
@@ -506,66 +502,32 @@ PyObject *CPyDict_GetItemUnsafe(PyObject *dict, PyObject *key) {
506502
return res;
507503
}
508504

509-
int CPyDict_SetItemUnsafe(PyObject *dict, PyObject *key, PyObject *value) {
510-
// No type check, direct call
511-
return PyDict_SetItem(dict, key, value);
512-
}
513-
514-
PyObject *CPyDict_KeysViewUnsafe(PyObject *dict) {
515-
// No type check, direct call
516-
return _CPyDictView_New(dict, &PyDictKeys_Type);
517-
}
518-
519-
PyObject *CPyDict_ValuesViewUnsafe(PyObject *dict) {
520-
// No type check, direct call
521-
return _CPyDictView_New(dict, &PyDictValues_Type);
522-
}
523-
524-
PyObject *CPyDict_ItemsViewUnsafe(PyObject *dict) {
525-
// No type check, direct call
526-
return _CPyDictView_New(dict, &PyDictItems_Type);
527-
}
528-
529-
PyObject *CPyDict_KeysUnsafe(PyObject *dict) {
530-
// No type check, direct call
531-
return PyDict_Keys(dict);
532-
}
533-
534-
PyObject *CPyDict_ValuesUnsafe(PyObject *dict) {
535-
// No type check, direct call
536-
return PyDict_Values(dict);
537-
}
538-
539-
PyObject *CPyDict_ItemsUnsafe(PyObject *dict) {
540-
// No type check, direct call
541-
return PyDict_Items(dict);
542-
}
543-
544-
char CPyDict_ClearUnsafe(PyObject *dict) {
545-
// No type check, direct call
546-
PyDict_Clear(dict);
547-
return 1;
548-
}
549-
550-
PyObject *CPyDict_CopyUnsafe(PyObject *dict) {
551-
// No type check, direct call
552-
return PyDict_Copy(dict);
553-
}
554-
555505
PyObject *CPyDict_GetKeysIterUnsafe(PyObject *dict) {
556-
// No type check, direct call
506+
// No type check, direct call. Returns dict directly to indicate fast path should be used.
557507
Py_INCREF(dict);
558508
return dict;
559509
}
560510

561511
PyObject *CPyDict_GetItemsIterUnsafe(PyObject *dict) {
562-
// No type check, direct call
512+
// No type check, direct call. Returns dict directly to indicate fast path should be used.
563513
Py_INCREF(dict);
564514
return dict;
565515
}
566516

567517
PyObject *CPyDict_GetValuesIterUnsafe(PyObject *dict) {
568-
// No type check, direct call
518+
// No type check, direct call. Returns dict directly to indicate fast path should be used.
569519
Py_INCREF(dict);
570520
return dict;
571521
}
522+
523+
PyObject *CPyDict_KeysViewUnsafe(PyObject *dict) {
524+
return _CPyDictView_New(dict, &PyDictKeys_Type);
525+
}
526+
527+
PyObject *CPyDict_ValuesViewUnsafe(PyObject *dict) {
528+
return _CPyDictView_New(dict, &PyDictValues_Type);
529+
}
530+
531+
PyObject *CPyDict_ItemsViewUnsafe(PyObject *dict) {
532+
return _CPyDictView_New(dict, &PyDictItems_Type);
533+
}

mypyc/primitives/dict_ops.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595
name="__setitem__",
9696
arg_types=[true_dict_rprimitive, object_rprimitive, object_rprimitive],
9797
return_type=c_int_rprimitive,
98-
c_function_name="CPyDict_SetItemUnsafe",
98+
c_function_name="PyDict_SetItem",
9999
error_kind=ERR_NEG_INT,
100100
)
101101

@@ -339,7 +339,7 @@
339339
name="clear",
340340
arg_types=[true_dict_rprimitive],
341341
return_type=bit_rprimitive,
342-
c_function_name="CPyDict_ClearUnsafe",
342+
c_function_name="PyDict_Clear",
343343
error_kind=ERR_FALSE,
344344
)
345345

@@ -353,11 +353,11 @@
353353
)
354354

355355
# dict.copy()
356-
method_op(
356+
true_dict_copy_op = method_op(
357357
name="copy",
358358
arg_types=[true_dict_rprimitive],
359359
return_type=true_dict_rprimitive,
360-
c_function_name="CPyDict_CopyUnsafe",
360+
c_function_name="PyDict_Copy",
361361
error_kind=ERR_MAGIC,
362362
)
363363

@@ -374,7 +374,7 @@
374374
true_dict_keys_op = custom_op(
375375
arg_types=[true_dict_rprimitive],
376376
return_type=list_rprimitive,
377-
c_function_name="CPyDict_KeysUnsafe",
377+
c_function_name="PyDict_Keys",
378378
error_kind=ERR_MAGIC,
379379
)
380380

@@ -390,7 +390,7 @@
390390
true_dict_values_op = custom_op(
391391
arg_types=[true_dict_rprimitive],
392392
return_type=list_rprimitive,
393-
c_function_name="CPyDict_ValuesUnsafe",
393+
c_function_name="PyDict_Values",
394394
error_kind=ERR_MAGIC,
395395
)
396396

@@ -406,7 +406,7 @@
406406
true_dict_items_op = custom_op(
407407
arg_types=[true_dict_rprimitive],
408408
return_type=list_rprimitive,
409-
c_function_name="CPyDict_ItemsUnsafe",
409+
c_function_name="PyDict_Items",
410410
error_kind=ERR_MAGIC,
411411
)
412412

@@ -514,6 +514,13 @@
514514
)
515515

516516
# Delete an item from a dict
517+
true_dict_del_item = custom_op(
518+
arg_types=[true_dict_rprimitive, object_rprimitive],
519+
return_type=c_int_rprimitive,
520+
c_function_name="PyDict_DelItem",
521+
error_kind=ERR_NEG_INT,
522+
)
523+
517524
dict_del_item = custom_op(
518525
arg_types=[object_rprimitive, object_rprimitive],
519526
return_type=c_int_rprimitive,

0 commit comments

Comments
 (0)