Created
December 15, 2013 15:09
-
-
Save kjelly/7974092 to your computer and use it in GitHub Desktop.
一般函數的捷徑,適用於那些參數沒 *args, 和 **kwargs 的函數
執行這類的函數比較快
詳見: Python 原碼解析 -- 深度探索動態語言核心技術 p223
或註解
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* The fast_function() function optimize calls for which no argument | |
tuple is necessary; the objects are passed directly from the stack. | |
For the simplest case -- a function that takes only positional | |
arguments and is called with only positional arguments -- it | |
inlines the most primitive frame setup code from | |
PyEval_EvalCodeEx(), which vastly reduces the checks that must be | |
done before evaluating the frame. | |
*/ | |
static PyObject * | |
fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk) | |
{ | |
PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); | |
PyObject *globals = PyFunction_GET_GLOBALS(func); | |
PyObject *argdefs = PyFunction_GET_DEFAULTS(func); | |
PyObject **d = NULL; | |
int nd = 0; | |
PCALL(PCALL_FUNCTION); | |
PCALL(PCALL_FAST_FUNCTION); | |
// 一般函數的捷徑 | |
if (argdefs == NULL && co->co_argcount == n && nk==0 && | |
co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { | |
PyFrameObject *f; | |
PyObject *retval = NULL; | |
PyThreadState *tstate = PyThreadState_GET(); | |
PyObject **fastlocals, **stack; | |
int i; | |
PCALL(PCALL_FASTER_FUNCTION); | |
assert(globals != NULL); | |
/* XXX Perhaps we should create a specialized | |
PyFrame_New() that doesn't take locals, but does | |
take builtins without sanity checking them. | |
*/ | |
assert(tstate != NULL); | |
f = PyFrame_New(tstate, co, globals, NULL); | |
if (f == NULL) | |
return NULL; | |
fastlocals = f->f_localsplus; | |
stack = (*pp_stack) - n; | |
for (i = 0; i < n; i++) { | |
Py_INCREF(*stack); | |
fastlocals[i] = *stack++; | |
} | |
retval = PyEval_EvalFrameEx(f,0); | |
++tstate->recursion_depth; | |
Py_DECREF(f); | |
--tstate->recursion_depth; | |
return retval; | |
} | |
if (argdefs != NULL) { | |
d = &PyTuple_GET_ITEM(argdefs, 0); | |
nd = Py_SIZE(argdefs); | |
} | |
return PyEval_EvalCodeEx(co, globals, | |
(PyObject *)NULL, (*pp_stack)-n, na, | |
(*pp_stack)-2*nk, nk, d, nd, | |
PyFunction_GET_CLOSURE(func)); | |
} |
closure 也會讓 vm 不會進入 "一般函數的捷徑"
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
函數預設參數也會減慢速度