Commit 8ddf15a3 authored by Stefan Behnel's avatar Stefan Behnel

rewrite dict.clear() optimisation to avoid redundant INCREF/DECREF of None in...

rewrite dict.clear() optimisation to avoid redundant INCREF/DECREF of None in the (normal) plain statement case
parent 15d5f621
...@@ -240,15 +240,6 @@ static PyObject* __Pyx_Intern(PyObject* s) { ...@@ -240,15 +240,6 @@ static PyObject* __Pyx_Intern(PyObject* s) {
} }
''') ''')
py_dict_clear_utility_code = UtilityCode(
proto = '''
static CYTHON_INLINE PyObject* __Pyx_PyDict_Clear(PyObject* d) {
PyDict_Clear(d);
Py_INCREF(Py_None);
return Py_None;
}
''')
py_set_utility_code = UtilityCode( py_set_utility_code = UtilityCode(
proto = """ proto = """
#if PY_VERSION_HEX < 0x02050000 #if PY_VERSION_HEX < 0x02050000
...@@ -504,8 +495,6 @@ builtin_types_table = [ ...@@ -504,8 +495,6 @@ builtin_types_table = [
("dict", "PyDict_Type", [BuiltinMethod("items", "T", "O", "PyDict_Items"), # FIXME: Py3 mode? ("dict", "PyDict_Type", [BuiltinMethod("items", "T", "O", "PyDict_Items"), # FIXME: Py3 mode?
BuiltinMethod("keys", "T", "O", "PyDict_Keys"), # FIXME: Py3 mode? BuiltinMethod("keys", "T", "O", "PyDict_Keys"), # FIXME: Py3 mode?
BuiltinMethod("values","T", "O", "PyDict_Values"), # FIXME: Py3 mode? BuiltinMethod("values","T", "O", "PyDict_Values"), # FIXME: Py3 mode?
BuiltinMethod("clear", "T", "O", "__Pyx_PyDict_Clear",
utility_code = py_dict_clear_utility_code),
BuiltinMethod("copy", "T", "T", "PyDict_Copy")]), BuiltinMethod("copy", "T", "T", "PyDict_Copy")]),
("slice", "PySlice_Type", [BuiltinAttribute('start'), ("slice", "PySlice_Type", [BuiltinAttribute('start'),
......
...@@ -2233,6 +2233,34 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -2233,6 +2233,34 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
### methods of builtin types ### methods of builtin types
PyDict_Clear_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_void_type, [
PyrexTypes.CFuncTypeArg("dict", Builtin.dict_type, None)
])
PyDict_Clear_Retval_func_type = PyrexTypes.CFuncType(
PyrexTypes.py_object_type, [
PyrexTypes.CFuncTypeArg("dict", Builtin.dict_type, None)
])
def _handle_simple_method_dict_clear(self, node, args, is_unbound_method):
"""Optimise dict.clear() differently, depending on the use (or
non-use) of the return value.
"""
if len(args) != 1:
return node
if node.result_is_used:
return self._substitute_method_call(
node, "__Pyx_PyDict_Clear", self.PyDict_Clear_Retval_func_type,
'clear', is_unbound_method, args,
may_return_none=True, is_temp=True,
utility_code=py_dict_clear_utility_code
).coerce_to(node.type, self.current_env)
else:
return self._substitute_method_call(
node, "PyDict_Clear", self.PyDict_Clear_func_type,
'clear', is_unbound_method, args, is_temp=False)
PyObject_Append_func_type = PyrexTypes.CFuncType( PyObject_Append_func_type = PyrexTypes.CFuncType(
PyrexTypes.py_object_type, [ PyrexTypes.py_object_type, [
PyrexTypes.CFuncTypeArg("list", PyrexTypes.py_object_type, None), PyrexTypes.CFuncTypeArg("list", PyrexTypes.py_object_type, None),
...@@ -2833,7 +2861,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -2833,7 +2861,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
def _substitute_method_call(self, node, name, func_type, def _substitute_method_call(self, node, name, func_type,
attr_name, is_unbound_method, args=(), attr_name, is_unbound_method, args=(),
utility_code=None, utility_code=None, is_temp=None,
may_return_none=ExprNodes.PythonCapiCallNode.may_return_none): may_return_none=ExprNodes.PythonCapiCallNode.may_return_none):
args = list(args) args = list(args)
if args and not args[0].is_literal: if args and not args[0].is_literal:
...@@ -2848,12 +2876,15 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -2848,12 +2876,15 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
error = "PyExc_AttributeError", error = "PyExc_AttributeError",
format_args = [attr_name]) format_args = [attr_name])
args[0] = self_arg args[0] = self_arg
if is_temp is None:
is_temp = node.is_temp
return ExprNodes.PythonCapiCallNode( return ExprNodes.PythonCapiCallNode(
node.pos, name, func_type, node.pos, name, func_type,
args = args, args = args,
is_temp = node.is_temp, is_temp = is_temp,
utility_code = utility_code, utility_code = utility_code,
may_return_none = may_return_none, may_return_none = may_return_none,
result_is_used = node.result_is_used,
) )
def _inject_int_default_argument(self, node, args, arg_index, type, default_value): def _inject_int_default_argument(self, node, args, arg_index, type, default_value):
...@@ -3166,6 +3197,16 @@ bad: ...@@ -3166,6 +3197,16 @@ bad:
) )
py_dict_clear_utility_code = UtilityCode(
proto = '''
static CYTHON_INLINE PyObject* __Pyx_PyDict_Clear(PyObject* d) {
PyDict_Clear(d);
Py_INCREF(Py_None);
return Py_None;
}
''')
pyobject_as_double_utility_code = UtilityCode( pyobject_as_double_utility_code = UtilityCode(
proto = ''' proto = '''
static double __Pyx__PyObject_AsDouble(PyObject* obj); /* proto */ static double __Pyx__PyObject_AsDouble(PyObject* obj); /* proto */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment