Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite0ce3e3

Browse files
[mypyc] feat:__mypyc_empty_tuple__ constant (#19654)
I realized that any time a user has a kwarg-only call expression like`fn(abc=123, ...)` in their compiled code, and `func` is not a nativefunction, a new empty tuple is created every timeThis is not really necessary, we can just hold the same empty tuple inmemory as a constant and pass it around. It's immutable, and that'salready what we're already doing, since `tuple() is tuple()` but ourcurrent method involves more steps.This should slightly improve the speed of kwarg-only python funccalling.
1 parente852829 commite0ce3e3

File tree

7 files changed

+51
-16
lines changed

7 files changed

+51
-16
lines changed

‎mypyc/codegen/emit.py‎

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,17 +1036,21 @@ def emit_box(
10361036
self.emit_line(f"{declaration}{dest} = PyFloat_FromDouble({src});")
10371037
elifisinstance(typ,RTuple):
10381038
self.declare_tuple_struct(typ)
1039-
self.emit_line(f"{declaration}{dest} = PyTuple_New({len(typ.types)});")
1040-
self.emit_line(f"if (unlikely({dest} == NULL))")
1041-
self.emit_line(" CPyError_OutOfMemory();")
1042-
# TODO: Fail if dest is None
1043-
foriinrange(len(typ.types)):
1044-
ifnottyp.is_unboxed:
1045-
self.emit_line(f"PyTuple_SET_ITEM({dest},{i},{src}.f{i}")
1046-
else:
1047-
inner_name=self.temp_name()
1048-
self.emit_box(f"{src}.f{i}",inner_name,typ.types[i],declare_dest=True)
1049-
self.emit_line(f"PyTuple_SET_ITEM({dest},{i},{inner_name});")
1039+
ifnottyp.types:
1040+
self.emit_line(f"{declaration}{dest} = CPyTuple_LoadEmptyTupleConstant();")
1041+
else:
1042+
self.emit_line(f"{declaration}{dest} = PyTuple_New({len(typ.types)});")
1043+
self.emit_line(f"if (unlikely({dest} == NULL))")
1044+
self.emit_line(" CPyError_OutOfMemory();")
1045+
1046+
# TODO: Fail if dest is None
1047+
foriinrange(len(typ.types)):
1048+
ifnottyp.is_unboxed:
1049+
self.emit_line(f"PyTuple_SET_ITEM({dest},{i},{src}.f{i}")
1050+
else:
1051+
inner_name=self.temp_name()
1052+
self.emit_box(f"{src}.f{i}",inner_name,typ.types[i],declare_dest=True)
1053+
self.emit_line(f"PyTuple_SET_ITEM({dest},{i},{inner_name});")
10501054
else:
10511055
assertnottyp.is_unboxed
10521056
# Type is boxed -- trivially just assign.

‎mypyc/irbuild/ll_builder.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@
189189
)
190190
frommypyc.primitives.tuple_opsimport (
191191
list_tuple_op,
192+
load_empty_tuple_constant_op,
192193
new_tuple_op,
193194
new_tuple_with_length_op,
194195
sequence_tuple_op,
@@ -2362,8 +2363,11 @@ def builtin_len(self, val: Value, line: int, use_pyssize_t: bool = False) -> Val
23622363
returnself.call_c(generic_len_op, [val],line)
23632364

23642365
defnew_tuple(self,items:list[Value],line:int)->Value:
2365-
size:Value=Integer(len(items),c_pyssize_t_rprimitive)
2366-
returnself.call_c(new_tuple_op, [size]+items,line)
2366+
ifitems:
2367+
size:Value=Integer(len(items),c_pyssize_t_rprimitive)
2368+
returnself.call_c(new_tuple_op, [size]+items,line)
2369+
else:
2370+
returnself.call_c(load_empty_tuple_constant_op, [],line)
23672371

23682372
defnew_tuple_with_length(self,length:Value,line:int)->Value:
23692373
"""This function returns an uninitialized tuple.

‎mypyc/lib-rt/CPy.h‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ typedef struct tuple_T4CIOO {
6464
}tuple_T4CIOO;
6565
#endif
6666

67+
// System-wide empty tuple constant
68+
externPyObject*__mypyc_empty_tuple__;
69+
70+
staticinlinePyObject*CPyTuple_LoadEmptyTupleConstant() {
71+
#if !CPY_3_12_FEATURES
72+
Py_INCREF(__mypyc_empty_tuple__);
73+
#endif
74+
return__mypyc_empty_tuple__;
75+
}
6776

6877
// Native object operations
6978

‎mypyc/lib-rt/init.c‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,21 @@
44
structExcDummyStruct_CPy_ExcDummyStruct= {PyObject_HEAD_INIT(NULL) };
55
PyObject*_CPy_ExcDummy= (PyObject*)&_CPy_ExcDummyStruct;
66

7+
// System-wide empty tuple constant
8+
PyObject*__mypyc_empty_tuple__=NULL;
9+
710
// Because its dynamic linker is more restricted than linux/OS X,
811
// Windows doesn't allow initializing globals with values from
912
// other dynamic libraries. This means we need to initialize
1013
// things at load time.
1114
voidCPy_Init(void) {
1215
_CPy_ExcDummyStruct.ob_base.ob_type=&PyBaseObject_Type;
16+
17+
// Initialize system-wide empty tuple constant
18+
if (__mypyc_empty_tuple__==NULL) {
19+
__mypyc_empty_tuple__=PyTuple_New(0);
20+
if (!__mypyc_empty_tuple__) {
21+
CPyError_OutOfMemory();
22+
}
23+
}
1324
}

‎mypyc/primitives/tuple_ops.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@
5555
error_kind=ERR_MAGIC,
5656
)
5757

58+
load_empty_tuple_constant_op=custom_op(
59+
arg_types=[],
60+
return_type=tuple_rprimitive,
61+
c_function_name="CPyTuple_LoadEmptyTupleConstant",
62+
error_kind=ERR_NEVER,
63+
)
64+
5865
# PyTuple_SET_ITEM does no error checking,
5966
# and should only be used to fill in brand new tuples.
6067
new_tuple_set_item_op=custom_op(

‎mypyc/test-data/irbuild-basic.test‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1750,7 +1750,7 @@ L0:
17501750
r7 = __main__.globals :: static
17511751
r8 = 'f'
17521752
r9 = CPyDict_GetItem(r7, r8)
1753-
r10 =PyTuple_Pack(0)
1753+
r10 =CPyTuple_LoadEmptyTupleConstant()
17541754
r11 = PyDict_Copy(r6)
17551755
r12 = PyObject_Call(r9, r10, r11)
17561756
r13 = unbox(tuple[int, int, int], r12)

‎mypyc/test-data/irbuild-classes.test‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ L2:
297297
r27 = CPyType_FromTemplate(r26, r24, r25)
298298
r28 = C_trait_vtable_setup()
299299
r29 = '__mypyc_attrs__'
300-
r30 =PyTuple_Pack(0)
300+
r30 =CPyTuple_LoadEmptyTupleConstant()
301301
r31 = PyObject_SetAttr(r27, r29, r30)
302302
r32 = r31 >= 0 :: signed
303303
__main__.C = r27 :: type
@@ -310,7 +310,7 @@ L2:
310310
r39 = __main__.S_template :: type
311311
r40 = CPyType_FromTemplate(r39, r37, r38)
312312
r41 = '__mypyc_attrs__'
313-
r42 =PyTuple_Pack(0)
313+
r42 =CPyTuple_LoadEmptyTupleConstant()
314314
r43 = PyObject_SetAttr(r40, r41, r42)
315315
r44 = r43 >= 0 :: signed
316316
__main__.S = r40 :: type

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp