self.positional_args,
self.keyword_args,
base_type.buffer_defaults)
-
+
+ if sys.version_info[0] < 3:
+ # Py 2.x enforces byte strings as keyword arguments ...
+ options = dict([ (name.encode('ASCII'), value)
+ for name, value in options.iteritems() ])
+
self.type = PyrexTypes.BufferType(base_type, **options)
return self.type
for item in self.items:
item.analyse_declarations(env, self.entry)
+ def analyse_expressions(self, env):
+ pass
+
def generate_execution_code(self, code):
if self.visibility == 'public':
temp = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
py_func = None
assmt = None
needs_closure = False
+ modifiers = []
def analyse_default_values(self, env):
genv = env.global_scope()
+ default_seen = 0
for arg in self.args:
if arg.default:
+ default_seen = 1
if arg.is_generic:
arg.default.analyse_types(env)
arg.default = arg.default.coerce_to(arg.type, genv)
error(arg.pos,
"This argument cannot have a default value")
arg.default = None
+ elif arg.kw_only:
+ default_seen = 1
+ elif default_seen:
+ error(arg.pos, "Non-default argument following default argument")
def need_gil_acquisition(self, lenv):
return 0
is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
self.entry.scope.is_c_class_scope)
+
+ profile = code.globalstate.directives['profile']
+ if profile:
+ if lenv.nogil:
+ error(self.pos, "Cannot profile nogil function.")
+ code.globalstate.use_utility_code(profile_utility_code)
# Generate C code for header and body of function
code.enter_cfunc_scope()
# ----- Extern library function declarations
lenv.generate_library_function_declarations(code)
# ----- GIL acquisition
- acquire_gil = self.need_gil_acquisition(lenv)
+ acquire_gil = self.acquire_gil
if acquire_gil:
env.use_utility_code(force_init_threads_utility_code)
code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
# ----- Automatic lead-ins for certain special functions
+ if profile:
+ code.put_trace_call(self.entry.name, self.pos)
if not lenv.nogil:
code.put_setup_refcount_context(self.entry.name)
if is_getbuffer_slot:
err_val = self.error_value()
exc_check = self.caller_will_check_exceptions()
if err_val is not None or exc_check:
+ # TODO: Fix exception tracing (though currently unused by cProfile).
+ # code.globalstate.use_utility_code(get_exception_tuple_utility_code)
+ # code.put_trace_exception()
code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
else:
warning(self.entry.pos, "Unraisable exception in function '%s'." \
# ----- Non-error return cleanup
- # If you add anything here, remember to add a condition to the
- # if-test above in the error block (so that it can jump past this
- # block).
code.put_label(code.return_label)
for entry in lenv.buffer_entries:
if entry.used:
# We do as Python instances and coerce -1 into -2.
code.putln("if (unlikely(%s == -1) && !PyErr_Occurred()) %s = -2;" % (Naming.retval_cname, Naming.retval_cname))
+ if profile:
+ if self.return_type.is_pyobject:
+ code.put_trace_return(Naming.retval_cname)
+ else:
+ code.put_trace_return("Py_None")
+
if acquire_gil:
code.putln("PyGILState_Release(_save);")
return self.entry.name
def analyse_declarations(self, env):
- directive_locals = self.directive_locals = env.directives['locals']
+ self.directive_locals.update(env.directives['locals'])
base_type = self.base_type.analyse(env)
# The 2 here is because we need both function and argument names.
name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
self.py_func.analyse_expressions(env)
else:
self.analyse_default_values(env)
+ self.acquire_gil = self.need_gil_acquisition(self.local_scope)
def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
arg_decls = []
is_wrapper = 0
decorators = None
entry = None
+ acquire_gil = 0
def __init__(self, pos, **kwds):
return
if self.entry.doc and Options.docstrings:
docstr = self.entry.doc
- if not isinstance(docstr, str):
+ if docstr.is_unicode:
docstr = docstr.utf8encode()
code.putln(
'static char %s[] = "%s";' % (
or self.starstar_arg is not None or has_kwonly_args
for arg in self.args:
- if not arg.type.is_pyobject and arg.type.from_py_function is None:
- arg.type.create_from_py_utility_code(env)
+ if not arg.type.is_pyobject:
+ done = arg.type.create_from_py_utility_code(env)
+ if not done: pass # will fail later
if not self.signature_has_generic_args():
if has_star_or_kw_args:
else:
positional_args = []
kw_only_args = []
- default_seen = 0
for arg in self.args:
arg_entry = arg.entry
if arg.is_generic:
if arg.default:
- default_seen = 1
if not arg.is_self_arg:
if arg.kw_only:
kw_only_args.append(arg)
positional_args.append(arg)
elif arg.kw_only:
kw_only_args.append(arg)
- default_seen = 1
- elif default_seen:
- error(arg.pos, "Non-default argument following default argument")
elif not arg.is_self_arg:
positional_args.append(arg)
code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
Naming.args_cname)
code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
- self.name.utf8encode(), Naming.args_cname, self.error_value()))
+ self.name, Naming.args_cname, self.error_value()))
code.putln("}")
code.globalstate.use_utility_code(keyword_string_check_utility_code)
pystring_cname = code.intern_identifier(arg.name)
# required keyword-only argument missing
code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
- self.name.utf8encode(),
+ self.name,
pystring_cname))
code.putln(code.error_goto(self.pos))
break
code.put_goto(success_label)
code.put_label(argtuple_error_label)
code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
- self.name.utf8encode(), has_fixed_positional_count,
+ self.name, has_fixed_positional_count,
min_positional_args, max_positional_args,
Naming.args_cname))
code.putln(code.error_goto(self.pos))
# arguments up to this point
code.putln('else {')
code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
- self.name.utf8encode(), has_fixed_positional_count,
+ self.name, has_fixed_positional_count,
min_positional_args, max_positional_args, i))
code.putln(code.error_goto(self.pos))
code.putln('}')
elif arg.kw_only:
code.putln('else {')
code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
- self.name.utf8encode(), pystring_cname))
+ self.name, pystring_cname))
code.putln(code.error_goto(self.pos))
code.putln('}')
if max_positional_args > 0:
Naming.pykwdlist_cname,
self.starstar_arg and self.starstar_arg.entry.cname or '0',
pos_arg_count,
- self.name.utf8encode()))
+ self.name))
code.putln(code.error_goto(self.pos))
code.putln('}')
PyObject *py_srcfile = 0;
PyObject *py_funcname = 0;
PyObject *py_globals = 0;
- PyObject *empty_string = 0;
PyCodeObject *py_code = 0;
PyFrameObject *py_frame = 0;
if (!py_funcname) goto bad;
py_globals = PyModule_GetDict(%(GLOBALS)s);
if (!py_globals) goto bad;
- #if PY_MAJOR_VERSION < 3
- empty_string = PyString_FromStringAndSize("", 0);
- #else
- empty_string = PyBytes_FromStringAndSize("", 0);
- #endif
- if (!empty_string) goto bad;
py_code = PyCode_New(
0, /*int argcount,*/
#if PY_MAJOR_VERSION >= 3
0, /*int nlocals,*/
0, /*int stacksize,*/
0, /*int flags,*/
- empty_string, /*PyObject *code,*/
+ %(EMPTY_BYTES)s, /*PyObject *code,*/
%(EMPTY_TUPLE)s, /*PyObject *consts,*/
%(EMPTY_TUPLE)s, /*PyObject *names,*/
%(EMPTY_TUPLE)s, /*PyObject *varnames,*/
py_srcfile, /*PyObject *filename,*/
py_funcname, /*PyObject *name,*/
%(LINENO)s, /*int firstlineno,*/
- empty_string /*PyObject *lnotab*/
+ %(EMPTY_BYTES)s /*PyObject *lnotab*/
);
if (!py_code) goto bad;
py_frame = PyFrame_New(
bad:
Py_XDECREF(py_srcfile);
Py_XDECREF(py_funcname);
- Py_XDECREF(empty_string);
Py_XDECREF(py_code);
Py_XDECREF(py_frame);
}
'CLINENO': Naming.clineno_cname,
'GLOBALS': Naming.module_cname,
'EMPTY_TUPLE' : Naming.empty_tuple,
+ 'EMPTY_BYTES' : Naming.empty_bytes,
})
restore_exception_utility_code = UtilityCode(
#------------------------------------------------------------------------------------
+get_exception_tuple_utility_code = UtilityCode(proto="""
+static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
+""",
+impl = """
+static PyObject *__Pyx_GetExceptionTuple(void) {
+ PyObject *type = NULL, *value = NULL, *tb = NULL;
+ if (__Pyx_GetException(&type, &value, &tb) == 0) {
+ PyObject* exc_info = PyTuple_New(3);
+ if (exc_info) {
+ Py_INCREF(type);
+ Py_INCREF(value);
+ Py_INCREF(tb);
+ PyTuple_SET_ITEM(exc_info, 0, type);
+ PyTuple_SET_ITEM(exc_info, 1, value);
+ PyTuple_SET_ITEM(exc_info, 2, tb);
+ return exc_info;
+ }
+ }
+ return NULL;
+}
+""",
+requires=[get_exception_utility_code])
+
+#------------------------------------------------------------------------------------
+
reset_exception_utility_code = UtilityCode(
proto = """
static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
""")
#------------------------------------------------------------------------------------
+
+# Note that cPython ignores PyTrace_EXCEPTION,
+# but maybe some other profilers don't.
+
+profile_utility_code = UtilityCode(proto="""
+#ifndef CYTHON_PROFILE
+#define CYTHON_PROFILE 1
+#endif
+
+#ifndef CYTHON_PROFILE_REUSE_FRAME
+#define CYTHON_PROFILE_REUSE_FRAME 0
+#endif
+
+#if CYTHON_PROFILE
+
+#include "compile.h"
+#include "frameobject.h"
+#include "traceback.h"
+
+#if CYTHON_PROFILE_REUSE_FRAME
+#define CYTHON_FRAME_MODIFIER static
+#define CYTHON_FRAME_DEL
+#else
+#define CYTHON_FRAME_MODIFIER
+#define CYTHON_FRAME_DEL Py_DECREF(%(FRAME)s)
+#endif
+
+#define __Pyx_TraceCall(funcname, srcfile, firstlineno) \\
+static PyCodeObject *%(FRAME_CODE)s = NULL; \\
+CYTHON_FRAME_MODIFIER PyFrameObject *%(FRAME)s = NULL; \\
+int __Pyx_use_tracing = 0; \\
+if (unlikely(PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc)) { \\
+ __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&%(FRAME_CODE)s, &%(FRAME)s, funcname, srcfile, firstlineno); \\
+}
+
+#define __Pyx_TraceException() \\
+if (unlikely(__Pyx_use_tracing( && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
+ PyObject *exc_info = __Pyx_GetExceptionTuple(); \\
+ if (exc_info) { \\
+ PyThreadState_GET()->c_profilefunc( \\
+ PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_EXCEPTION, exc_info); \\
+ Py_DECREF(exc_info); \\
+ } \\
+}
+
+#define __Pyx_TraceReturn(result) \\
+if (unlikely(__Pyx_use_tracing) && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
+ PyThreadState_GET()->c_profilefunc( \\
+ PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_RETURN, (PyObject*)result); \\
+ CYTHON_FRAME_DEL; \\
+}
+
+static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno); /*proto*/
+static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, const char *funcname, const char *srcfile, int firstlineno); /*proto*/
+
+#else
+#define __Pyx_TraceCall(funcname, srcfile, firstlineno)
+#define __Pyx_TraceException()
+#define __Pyx_TraceReturn(result)
+#endif /* CYTHON_PROFILE */
+"""
+% {
+ "FRAME": Naming.frame_cname,
+ "FRAME_CODE": Naming.frame_code_cname,
+},
+impl = """
+
+#if CYTHON_PROFILE
+
+static int __Pyx_TraceSetupAndCall(PyCodeObject** code,
+ PyFrameObject** frame,
+ const char *funcname,
+ const char *srcfile,
+ int firstlineno) {
+ if (*frame == NULL || !CYTHON_PROFILE_REUSE_FRAME) {
+ if (*code == NULL) {
+ *code = __Pyx_createFrameCodeObject(funcname, srcfile, firstlineno);
+ if (*code == NULL) return 0;
+ }
+ *frame = PyFrame_New(
+ PyThreadState_GET(), /*PyThreadState *tstate*/
+ *code, /*PyCodeObject *code*/
+ PyModule_GetDict(%(MODULE)s), /*PyObject *globals*/
+ 0 /*PyObject *locals*/
+ );
+ if (*frame == NULL) return 0;
+ }
+ else {
+ (*frame)->f_tstate = PyThreadState_GET();
+ }
+ return PyThreadState_GET()->c_profilefunc(PyThreadState_GET()->c_profileobj, *frame, PyTrace_CALL, NULL) == 0;
+}
+
+static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno) {
+ PyObject *py_srcfile = 0;
+ PyObject *py_funcname = 0;
+ PyCodeObject *py_code = 0;
+
+ #if PY_MAJOR_VERSION < 3
+ py_funcname = PyString_FromString(funcname);
+ py_srcfile = PyString_FromString(srcfile);
+ #else
+ py_funcname = PyUnicode_FromString(funcname);
+ py_srcfile = PyUnicode_FromString(srcfile);
+ #endif
+ if (!py_funcname | !py_srcfile) goto bad;
+
+ py_code = PyCode_New(
+ 0, /*int argcount,*/
+ #if PY_MAJOR_VERSION >= 3
+ 0, /*int kwonlyargcount,*/
+ #endif
+ 0, /*int nlocals,*/
+ 0, /*int stacksize,*/
+ 0, /*int flags,*/
+ %(EMPTY_BYTES)s, /*PyObject *code,*/
+ %(EMPTY_TUPLE)s, /*PyObject *consts,*/
+ %(EMPTY_TUPLE)s, /*PyObject *names,*/
+ %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
+ %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
+ %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
+ py_srcfile, /*PyObject *filename,*/
+ py_funcname, /*PyObject *name,*/
+ firstlineno, /*int firstlineno,*/
+ %(EMPTY_BYTES)s /*PyObject *lnotab*/
+ );
+
+bad:
+ Py_XDECREF(py_srcfile);
+ Py_XDECREF(py_funcname);
+
+ return py_code;
+}
+
+#endif /* CYTHON_PROFILE */
+""" % {
+ 'EMPTY_TUPLE' : Naming.empty_tuple,
+ 'EMPTY_BYTES' : Naming.empty_bytes,
+ "MODULE": Naming.module_cname,
+})