Commit 054e4d13 authored by Stefan Behnel's avatar Stefan Behnel

make sure we only optimise builtins and no user defined names, support further...

make sure we only optimise builtins and no user defined names, support further optimisations on builtins that were already replaced with C functions
parent eda4dc98
...@@ -740,19 +740,22 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -740,19 +740,22 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
arg_tuple = node.positional_args arg_tuple = node.positional_args
if not isinstance(arg_tuple, ExprNodes.TupleNode): if not isinstance(arg_tuple, ExprNodes.TupleNode):
return node return node
args = arg_tuple.args
return self._dispatch_to_handler( return self._dispatch_to_handler(
node, function, arg_tuple, node.keyword_args) node, function, args, node.keyword_args)
def visit_SimpleCallNode(self, node): def visit_SimpleCallNode(self, node):
self.visitchildren(node) self.visitchildren(node)
function = node.function function = node.function
if not function.type.is_pyobject: if function.type.is_pyobject:
return node
arg_tuple = node.arg_tuple arg_tuple = node.arg_tuple
if not isinstance(arg_tuple, ExprNodes.TupleNode): if not isinstance(arg_tuple, ExprNodes.TupleNode):
return node return node
args = arg_tuple.args
else:
args = node.args
return self._dispatch_to_handler( return self._dispatch_to_handler(
node, node.function, arg_tuple) node, function, args)
### cleanup to avoid redundant coercions to/from Python types ### cleanup to avoid redundant coercions to/from Python types
...@@ -823,20 +826,25 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -823,20 +826,25 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
handler = getattr(self, '_handle_any_%s' % match_name, None) handler = getattr(self, '_handle_any_%s' % match_name, None)
return handler return handler
def _dispatch_to_handler(self, node, function, arg_tuple, kwargs=None): def _dispatch_to_handler(self, node, function, arg_list, kwargs=None):
if function.is_name: if function.is_name:
match_name = "_function_%s" % function.name # we only consider functions that are either builtin
# Python functions or builtins that were already replaced
# into a C function call (defined in the builtin scope)
is_builtin = function.entry.is_builtin \
or getattr(function.entry, 'scope', None) is Builtin.builtin_scope
if not is_builtin:
return node
function_handler = self._find_handler( function_handler = self._find_handler(
"function_%s" % function.name, kwargs) "function_%s" % function.name, kwargs)
if function_handler is None: if function_handler is None:
return node return node
if kwargs: if kwargs:
return function_handler(node, arg_tuple, kwargs) return function_handler(node, arg_list, kwargs)
else: else:
return function_handler(node, arg_tuple) return function_handler(node, arg_list)
elif function.is_attribute: elif function.is_attribute and function.type.is_pyobject:
attr_name = function.attribute attr_name = function.attribute
arg_list = arg_tuple.args
self_arg = function.obj self_arg = function.obj
obj_type = self_arg.type obj_type = self_arg.type
is_unbound_method = False is_unbound_method = False
...@@ -892,7 +900,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -892,7 +900,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
"""Replace dict(a=b,c=d,...) by the underlying keyword dict """Replace dict(a=b,c=d,...) by the underlying keyword dict
construction which is done anyway. construction which is done anyway.
""" """
if len(pos_args.args) > 0: if len(pos_args) > 0:
return node return node
if not isinstance(kwargs, ExprNodes.DictNode): if not isinstance(kwargs, ExprNodes.DictNode):
return node return node
...@@ -910,9 +918,9 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -910,9 +918,9 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
"""Replace dict(some_dict) by PyDict_Copy(some_dict) and """Replace dict(some_dict) by PyDict_Copy(some_dict) and
dict([ (a,b) for ... ]) by a literal { a:b for ... }. dict([ (a,b) for ... ]) by a literal { a:b for ... }.
""" """
if len(pos_args.args) != 1: if len(pos_args) != 1:
return node return node
arg = pos_args.args[0] arg = pos_args[0]
if arg.type is Builtin.dict_type: if arg.type is Builtin.dict_type:
arg = ExprNodes.NoneCheckNode( arg = ExprNodes.NoneCheckNode(
arg, "PyExc_TypeError", "'NoneType' is not iterable") arg, "PyExc_TypeError", "'NoneType' is not iterable")
...@@ -943,13 +951,13 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -943,13 +951,13 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
"""Replace set([a,b,...]) by a literal set {a,b,...} and """Replace set([a,b,...]) by a literal set {a,b,...} and
set([ x for ... ]) by a literal { x for ... }. set([ x for ... ]) by a literal { x for ... }.
""" """
arg_count = len(pos_args.args) arg_count = len(pos_args)
if arg_count == 0: if arg_count == 0:
return ExprNodes.SetNode(node.pos, args=[], return ExprNodes.SetNode(node.pos, args=[],
type=Builtin.set_type, is_temp=1) type=Builtin.set_type, is_temp=1)
if arg_count > 1: if arg_count > 1:
return node return node
iterable = pos_args.args[0] iterable = pos_args[0]
if isinstance(iterable, (ExprNodes.ListNode, ExprNodes.TupleNode)): if isinstance(iterable, (ExprNodes.ListNode, ExprNodes.TupleNode)):
return ExprNodes.SetNode(node.pos, args=iterable.args, return ExprNodes.SetNode(node.pos, args=iterable.args,
type=Builtin.set_type, is_temp=1) type=Builtin.set_type, is_temp=1)
...@@ -971,20 +979,20 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -971,20 +979,20 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
def _handle_simple_function_tuple(self, node, pos_args): def _handle_simple_function_tuple(self, node, pos_args):
"""Replace tuple([...]) by a call to PyList_AsTuple. """Replace tuple([...]) by a call to PyList_AsTuple.
""" """
if len(pos_args.args) != 1: if len(pos_args) != 1:
return node return node
list_arg = pos_args.args[0] list_arg = pos_args[0]
if list_arg.type is not Builtin.list_type: if list_arg.type is not Builtin.list_type:
return node return node
if not isinstance(list_arg, (ExprNodes.ComprehensionNode, if not isinstance(list_arg, (ExprNodes.ComprehensionNode,
ExprNodes.ListNode)): ExprNodes.ListNode)):
pos_args.args[0] = ExprNodes.NoneCheckNode( pos_args[0] = ExprNodes.NoneCheckNode(
list_arg, "PyExc_TypeError", list_arg, "PyExc_TypeError",
"'NoneType' object is not iterable") "'NoneType' object is not iterable")
return ExprNodes.PythonCapiCallNode( return ExprNodes.PythonCapiCallNode(
node.pos, "PyList_AsTuple", self.PyList_AsTuple_func_type, node.pos, "PyList_AsTuple", self.PyList_AsTuple_func_type,
args = pos_args.args, args = pos_args,
is_temp = node.is_temp is_temp = node.is_temp
) )
...@@ -1004,22 +1012,21 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -1004,22 +1012,21 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
]) ])
def _handle_simple_function_getattr(self, node, pos_args): def _handle_simple_function_getattr(self, node, pos_args):
args = pos_args.args if len(pos_args) == 2:
if len(args) == 2:
node = ExprNodes.PythonCapiCallNode( node = ExprNodes.PythonCapiCallNode(
node.pos, "PyObject_GetAttr", self.PyObject_GetAttr2_func_type, node.pos, "PyObject_GetAttr", self.PyObject_GetAttr2_func_type,
args = args, args = pos_args,
is_temp = node.is_temp is_temp = node.is_temp
) )
elif len(args) == 3: elif len(pos_args) == 3:
node = ExprNodes.PythonCapiCallNode( node = ExprNodes.PythonCapiCallNode(
node.pos, "__Pyx_GetAttr3", self.PyObject_GetAttr3_func_type, node.pos, "__Pyx_GetAttr3", self.PyObject_GetAttr3_func_type,
utility_code = Builtin.getattr3_utility_code, utility_code = Builtin.getattr3_utility_code,
args = args, args = pos_args,
is_temp = node.is_temp is_temp = node.is_temp
) )
else: else:
self._error_wrong_arg_count('getattr', node, args, '2 or 3') self._error_wrong_arg_count('getattr', node, pos_args, '2 or 3')
return node return node
Pyx_Type_func_type = PyrexTypes.CFuncType( Pyx_Type_func_type = PyrexTypes.CFuncType(
...@@ -1028,12 +1035,11 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -1028,12 +1035,11 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
]) ])
def _handle_simple_function_type(self, node, pos_args): def _handle_simple_function_type(self, node, pos_args):
args = pos_args.args if len(pos_args) != 1:
if len(args) != 1:
return node return node
node = ExprNodes.PythonCapiCallNode( node = ExprNodes.PythonCapiCallNode(
node.pos, "__Pyx_Type", self.Pyx_Type_func_type, node.pos, "__Pyx_Type", self.Pyx_Type_func_type,
args = args, args = pos_args,
is_temp = node.is_temp, is_temp = node.is_temp,
utility_code = pytype_utility_code, utility_code = pytype_utility_code,
) )
......
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