Commit e13fa642 authored by Stefan Behnel's avatar Stefan Behnel

avoid exit overhead in inlined generator expressions by directly returning the...

avoid exit overhead in inlined generator expressions by directly returning the result instead of raising a StopIteration with value
parent 13ace3a9
......@@ -7328,6 +7328,11 @@ class InlinedGeneratorExpressionNode(ExprNode):
orig_func = None
type = py_object_type
def __init__(self, pos, gen, **kwargs):
gen.def_node.gbody.is_inlined = True
kwargs['gen'] = gen
super(InlinedGeneratorExpressionNode, self).__init__(pos, **kwargs)
def may_be_none(self):
return self.orig_func not in ('any', 'all')
......@@ -7340,8 +7345,7 @@ class InlinedGeneratorExpressionNode(ExprNode):
return self
def generate_result_code(self, code):
code.globalstate.use_utility_code(UtilityCode.load_cached("GetGenexpResult", "Coroutine.c"))
code.putln("%s = __Pyx_Generator_GetGenexpResult(%s); %s" % (
code.putln("%s = __Pyx_Generator_Next(%s); %s" % (
self.result(), self.gen.result(),
code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
......
......@@ -3995,6 +3995,7 @@ class GeneratorBodyDefNode(DefNode):
#
is_generator_body = True
is_inlined = False
def __init__(self, pos=None, name=None, body=None):
super(GeneratorBodyDefNode, self).__init__(
......@@ -4090,12 +4091,15 @@ class GeneratorBodyDefNode(DefNode):
# ----- Non-error return cleanup
code.put_label(code.return_label)
code.put_xdecref(Naming.retval_cname, py_object_type)
if self.is_inlined:
code.put_xgiveref(Naming.retval_cname)
else:
code.put_xdecref_clear(Naming.retval_cname, py_object_type)
code.putln('%s->resume_label = -1;' % Naming.generator_cname)
# clean up as early as possible to help breaking any reference cycles
code.putln('__Pyx_Coroutine_clear((PyObject*)%s);' % Naming.generator_cname)
code.put_finish_refcount_context()
code.putln('return NULL;')
code.putln("return %s;" % Naming.retval_cname)
code.putln("}")
# ----- Go back and insert temp variable declarations
......
......@@ -1545,8 +1545,7 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
condition=condition,
body=Nodes.ReturnStatNode(
node.pos,
value=ExprNodes.BoolNode(yield_expression.pos, value=is_any, constant_result=is_any),
in_generator=True)
value=ExprNodes.BoolNode(yield_expression.pos, value=is_any, constant_result=is_any))
)]
)
loop = loop_node
......@@ -1560,8 +1559,7 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
loop = next_loop
loop_node.else_clause = Nodes.ReturnStatNode(
node.pos,
value=ExprNodes.BoolNode(yield_expression.pos, value=not is_any, constant_result=not is_any),
in_generator=True)
value=ExprNodes.BoolNode(yield_expression.pos, value=not is_any, constant_result=not is_any))
Visitor.recursively_replace_node(loop_node, yield_stat_node, test_node)
......
......@@ -246,28 +246,6 @@ static void __Pyx_Generator_Replace_StopIteration(void) {
}
//////////////////// GetGenexpResult.proto ////////////////////
static CYTHON_INLINE PyObject* __Pyx_Generator_GetGenexpResult(PyObject* gen); /*proto*/
//////////////////// GetGenexpResult ////////////////////
//@requires: Generator
static CYTHON_INLINE PyObject* __Pyx_Generator_GetGenexpResult(PyObject* gen) {
PyObject *result;
result = __Pyx_Generator_Next(gen);
if (unlikely(result)) {
PyErr_Format(PyExc_RuntimeError, "Generator expression returned with non-StopIteration result '%.100s'",
result ? Py_TYPE(result)->tp_name : "NULL");
Py_XDECREF(result);
return NULL;
}
if (unlikely(__Pyx_PyGen_FetchStopIterationValue(&result) < 0))
return NULL;
return result;
}
//////////////////// CoroutineBase.proto ////////////////////
typedef PyObject *(*__pyx_coroutine_body_t)(PyObject *, PyObject *);
......@@ -323,6 +301,7 @@ static PyTypeObject *__pyx_GeneratorType = 0;
#define __Pyx_Generator_New(body, closure, name, qualname) \
__Pyx__Coroutine_New(__pyx_GeneratorType, body, closure, name, qualname)
static PyObject *__Pyx_Generator_Next(PyObject *self);
static int __pyx_Generator_init(void); /*proto*/
......@@ -337,7 +316,6 @@ static int __pyx_Generator_init(void); /*proto*/
#include <structmember.h>
#include <frameobject.h>
static PyObject *__Pyx_Generator_Next(PyObject *self);
static PyObject *__Pyx_Coroutine_Send(PyObject *self, PyObject *value);
static PyObject *__Pyx_Coroutine_Close(PyObject *self);
static PyObject *__Pyx_Coroutine_Throw(PyObject *gen, PyObject *args);
......
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