Commit 6b84a0fb authored by Stefan Behnel's avatar Stefan Behnel

enable method call optimisation on all simple Python calls as PyMethod_Check()...

enable method call optimisation on all simple Python calls as PyMethod_Check() should be cheap enough
parent 7ab811ce
...@@ -4837,7 +4837,21 @@ class PyMethodCallNode(SimpleCallNode): ...@@ -4837,7 +4837,21 @@ class PyMethodCallNode(SimpleCallNode):
arg_offset_cname = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False) arg_offset_cname = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False)
code.putln("%s = 0;" % arg_offset_cname) code.putln("%s = 0;" % arg_offset_cname)
code.putln("if (CYTHON_COMPILING_IN_CPYTHON && likely(PyMethod_Check(%s))) {" % function) if self.function.is_attribute and self.function.obj.type is not Builtin.type_type:
likely_method = 'likely'
elif self.function.is_name and self.function.cf_state:
# not an attribute itself, but might have been assigned from one (e.g. bound method)
for assignment in self.function.cf_state:
value = assignment.rhs
if value.is_attribute and value.obj.type.is_pyobject and value.obj.type is not Builtin.type_type:
likely_method = 'likely'
break
else:
likely_method = 'unlikely'
else:
likely_method = 'unlikely'
code.putln("if (CYTHON_COMPILING_IN_CPYTHON && %s(PyMethod_Check(%s))) {" % (likely_method, function))
code.putln("%s = PyMethod_GET_SELF(%s);" % (self_arg, function)) code.putln("%s = PyMethod_GET_SELF(%s);" % (self_arg, function))
# the following is always true in Py3 (kept only for safety), # the following is always true in Py3 (kept only for safety),
# but is false for unbound methods in Py2 # but is false for unbound methods in Py2
......
...@@ -3763,22 +3763,11 @@ class FinalOptimizePhase(Visitor.CythonTransform, Visitor.NodeRefCleanupMixin): ...@@ -3763,22 +3763,11 @@ class FinalOptimizePhase(Visitor.CythonTransform, Visitor.NodeRefCleanupMixin):
node.function.type = node.function.entry.type node.function.type = node.function.entry.type
PyTypeObjectPtr = PyrexTypes.CPtrType(cython_scope.lookup('PyTypeObject').type) PyTypeObjectPtr = PyrexTypes.CPtrType(cython_scope.lookup('PyTypeObject').type)
node.args[1] = ExprNodes.CastNode(node.args[1], PyTypeObjectPtr) node.args[1] = ExprNodes.CastNode(node.args[1], PyTypeObjectPtr)
elif node.function.type.is_pyobject and node.function.type is not Builtin.type_type: elif node.is_temp and node.function.type.is_pyobject and node.function.type is not Builtin.type_type:
# we could do it for all calls, but attributes are most likely to result in a method call if isinstance(node.arg_tuple, ExprNodes.TupleNode) and not (
function = node.function node.arg_tuple.mult_factor or (node.arg_tuple.is_literal and node.arg_tuple.args)):
likely_method = function.is_attribute node = self.replace(node, ExprNodes.PyMethodCallNode.from_node(
if not likely_method and function.is_name and function.cf_state: node, function=node.function, arg_tuple=node.arg_tuple, type=node.type))
# not an attribute itself, but might have been assigned from one (e.g. bound method)
for assignment in function.cf_state:
value = assignment.rhs
if value.is_attribute and value.obj.type.is_pyobject and value.obj.type is not Builtin.type_type:
likely_method = True
break
if likely_method:
if isinstance(node.arg_tuple, ExprNodes.TupleNode) and not (
node.arg_tuple.mult_factor or (node.arg_tuple.is_literal and node.arg_tuple.args)):
node = self.replace(node, ExprNodes.PyMethodCallNode.from_node(
node, function=node.function, arg_tuple=node.arg_tuple, type=node.type))
return node return node
def visit_PyTypeTestNode(self, node): def visit_PyTypeTestNode(self, node):
......
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