mirror of
https://github.com/python/cpython.git
synced 2024-11-25 19:03:49 +08:00
985eba53f5
-DCALL_PROFILE: Count the number of function calls executed. When this symbol is defined, the ceval mainloop and helper functions count the number of function calls made. It keeps detailed statistics about what kind of object was called and whether the call hit any of the special fast paths in the code. Optimization: When we take the fast_function() path, which seems to be taken for most function calls, and there is minimal frame setup to do, avoid call PyEval_EvalCodeEx(). The eval code ex function does a lot of work to handle keywords args and star args, free variables, generators, etc. The inlined version simply allocates the frame and copies the arguments values into the frame. The optimization gets a little help from compile.c which adds a CO_NOFREE flag to code objects that don't have free variables or cell variables. This change allows fast_function() to get into the fast path with fewer tests. I measure a couple of percent speedup in pystone with this change, but there's surely more that can be done.
93 lines
3.3 KiB
C
93 lines
3.3 KiB
C
|
|
/* Definitions for bytecode */
|
|
|
|
#ifndef Py_COMPILE_H
|
|
#define Py_COMPILE_H
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* Bytecode object */
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
int co_argcount; /* #arguments, except *args */
|
|
int co_nlocals; /* #local variables */
|
|
int co_stacksize; /* #entries needed for evaluation stack */
|
|
int co_flags; /* CO_..., see below */
|
|
PyObject *co_code; /* instruction opcodes */
|
|
PyObject *co_consts; /* list (constants used) */
|
|
PyObject *co_names; /* list of strings (names used) */
|
|
PyObject *co_varnames; /* tuple of strings (local variable names) */
|
|
PyObject *co_freevars; /* tuple of strings (free variable names) */
|
|
PyObject *co_cellvars; /* tuple of strings (cell variable names) */
|
|
/* The rest doesn't count for hash/cmp */
|
|
PyObject *co_filename; /* string (where it was loaded from) */
|
|
PyObject *co_name; /* string (name, for reference) */
|
|
int co_firstlineno; /* first source line number */
|
|
PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) */
|
|
} PyCodeObject;
|
|
|
|
/* Masks for co_flags above */
|
|
#define CO_OPTIMIZED 0x0001
|
|
#define CO_NEWLOCALS 0x0002
|
|
#define CO_VARARGS 0x0004
|
|
#define CO_VARKEYWORDS 0x0008
|
|
#define CO_NESTED 0x0010
|
|
#define CO_GENERATOR 0x0020
|
|
/* The CO_NOFREE flag is set if there are no free or cell variables.
|
|
This information is redundant, but it allows a single flag test
|
|
to determine whether there is any extra work to be done when the
|
|
call frame it setup.
|
|
*/
|
|
#define CO_NOFREE 0x0040
|
|
/* XXX Temporary hack. Until generators are a permanent part of the
|
|
language, we need a way for a code object to record that generators
|
|
were *possible* when it was compiled. This is so code dynamically
|
|
compiled *by* a code object knows whether to allow yield stmts. In
|
|
effect, this passes on the "from __future__ import generators" state
|
|
in effect when the code block was compiled. */
|
|
#define CO_GENERATOR_ALLOWED 0x1000 /* no longer used in an essential way */
|
|
#define CO_FUTURE_DIVISION 0x2000
|
|
|
|
PyAPI_DATA(PyTypeObject) PyCode_Type;
|
|
|
|
#define PyCode_Check(op) ((op)->ob_type == &PyCode_Type)
|
|
#define PyCode_GetNumFree(op) (PyTuple_GET_SIZE((op)->co_freevars))
|
|
|
|
#define CO_MAXBLOCKS 20 /* Max static block nesting within a function */
|
|
|
|
/* Public interface */
|
|
struct _node; /* Declare the existence of this type */
|
|
PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *);
|
|
PyAPI_FUNC(PyCodeObject *) PyCode_New(
|
|
int, int, int, int, PyObject *, PyObject *, PyObject *, PyObject *,
|
|
PyObject *, PyObject *, PyObject *, PyObject *, int, PyObject *);
|
|
/* same as struct above */
|
|
PyAPI_FUNC(int) PyCode_Addr2Line(PyCodeObject *, int);
|
|
|
|
/* Future feature support */
|
|
|
|
typedef struct {
|
|
int ff_found_docstring;
|
|
int ff_last_lineno;
|
|
int ff_features;
|
|
} PyFutureFeatures;
|
|
|
|
PyAPI_FUNC(PyFutureFeatures *) PyNode_Future(struct _node *, const char *);
|
|
PyAPI_FUNC(PyCodeObject *) PyNode_CompileFlags(struct _node *, const char *,
|
|
PyCompilerFlags *);
|
|
|
|
#define FUTURE_NESTED_SCOPES "nested_scopes"
|
|
#define FUTURE_GENERATORS "generators"
|
|
#define FUTURE_DIVISION "division"
|
|
|
|
/* for internal use only */
|
|
#define _PyCode_GETCODEPTR(co, pp) \
|
|
((*(co)->co_code->ob_type->tp_as_buffer->bf_getreadbuffer) \
|
|
((co)->co_code, 0, (void **)(pp)))
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif /* !Py_COMPILE_H */
|