Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(50378)

Delta Between Two Patch Sets: Python/ceval.c

Issue 27809: _PyObject_FastCall(): add support for keyword arguments
Left Patch Set: Created 3 years, 1 month ago
Right Patch Set: Created 3 years, 1 month ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Objects/typeobject.c ('k') | Python/pythonrun.c » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 1
2 /* Execute compiled code */ 2 /* Execute compiled code */
3 3
4 /* XXX TO DO: 4 /* XXX TO DO:
5 XXX speed up searching for keywords by using a dictionary 5 XXX speed up searching for keywords by using a dictionary
6 XXX document it! 6 XXX document it!
7 */ 7 */
8 8
9 /* enable more aggressive intra-module optimizations, where available */ 9 /* enable more aggressive intra-module optimizations, where available */
10 #define PY_LOCAL_AGGRESSIVE 10 #define PY_LOCAL_AGGRESSIVE
(...skipping 3766 matching lines...) Expand 10 before | Expand all | Expand 10 after
3777 given == 1 && !kwonly_given ? "was" : "were"); 3777 given == 1 && !kwonly_given ? "was" : "were");
3778 Py_DECREF(sig); 3778 Py_DECREF(sig);
3779 Py_DECREF(kwonly_sig); 3779 Py_DECREF(kwonly_sig);
3780 } 3780 }
3781 3781
3782 3782
3783 /* This is gonna seem *real weird*, but if you put some other code between 3783 /* This is gonna seem *real weird*, but if you put some other code between
3784 PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust 3784 PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust
3785 the test in the if statements in Misc/gdbinit (pystack and pystackv). */ 3785 the test in the if statements in Misc/gdbinit (pystack and pystackv). */
3786 3786
3787 static int
3788 fastlocals_dict(PyObject **fastlocals, PyCodeObject *co,
3789 PyObject *kwdict, PyObject *kwargs)
3790 {
3791 const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount;
3792 _Py_IDENTIFIER(items);
3793 PyObject *items, *iter;
3794 PyObject *item = NULL;
3795 PyObject **co_varnames;
3796
3797 assert(PyDict_Check(kwargs));
3798
3799 if (total_args == 0 && kwdict != NULL) {
3800 if (PyDict_Update(kwdict, kwargs) < 0) {
3801 return -1;
3802 }
3803 return 0;
3804 }
3805
3806 items = _PyObject_CallMethodId((PyObject *)kwargs, &PyId_items, NULL);
3807 if (items == NULL) {
3808 return -1;
3809 }
3810
3811 iter = PyObject_GetIter(items);
3812 Py_DECREF(items);
3813 if (iter == NULL) {
3814 goto fail;
3815 }
3816
3817 co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item;
3818 do {
3819 PyObject *keyword, *value;
3820 int j;
3821
3822 /* Get first item */
3823 item = PyIter_Next(iter);
3824 if (item == NULL) {
3825 if (PyErr_Occurred()) {
3826 goto fail;
3827 }
3828
3829 /* nothing more to add */
3830 break;
3831 }
3832 assert(PyTuple_CheckExact(item) && PyTuple_GET_SIZE(item) == 2);
3833
3834 keyword = PyTuple_GET_ITEM(item, 0);
3835 value = PyTuple_GET_ITEM(item, 1);
3836
3837 if (keyword == NULL || !PyUnicode_Check(keyword)) {
3838 PyErr_Format(PyExc_TypeError,
3839 "%U() keywords must be strings",
3840 co->co_name);
3841 goto fail;
3842 }
3843
3844 /* Speed hack: do raw pointer compares. As names are
3845 normally interned this should almost always hit. */
3846 for (j = 0; j < total_args; j++) {
3847 PyObject *name = co_varnames[j];
3848 if (name == keyword) {
3849 goto kw_found;
3850 }
3851 }
3852
3853 /* Slow fallback, just in case */
3854 for (j = 0; j < total_args; j++) {
3855 PyObject *name = co_varnames[j];
3856 int cmp = PyObject_RichCompareBool(keyword, name, Py_EQ);
3857 if (cmp > 0) {
3858 goto kw_found;
3859 }
3860 else if (cmp < 0) {
3861 goto fail;
3862 }
3863 }
3864
3865 if (j >= total_args && kwdict == NULL) {
3866 PyErr_Format(PyExc_TypeError,
3867 "%U() got an unexpected keyword argument '%S'",
3868 co->co_name, keyword);
3869 goto fail;
3870 }
3871
3872 if (PyDict_SetItem(kwdict, keyword, value) == -1) {
3873 goto fail;
3874 }
3875 Py_DECREF(item);
3876 continue;
3877
3878 kw_found:
3879 if (GETLOCAL(j) != NULL) {
3880 PyErr_Format(PyExc_TypeError,
3881 "%U() got multiple values for argument '%S'",
3882 co->co_name,
3883 keyword);
3884 goto fail;
3885 }
3886 Py_INCREF(value);
3887 SETLOCAL(j, value);
3888
3889 Py_DECREF(item);
3890 } while (1);
3891
3892 Py_DECREF(iter);
3893 return 0;
3894
3895 fail:
3896 Py_DECREF(iter);
3897 Py_XDECREF(item);
3898 return -1;
3899 }
3900
3901 static PyObject * 3787 static PyObject *
3902 _PyEval_EvalCode(PyObject *_co, PyObject *globals, PyObject *locals, 3788 _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
3903 PyObject **args, int argcount, 3789 PyObject **args, int argcount, PyObject **kws, int kwcount,
3904 PyObject **kws, int kwcount, PyObject *kwargs, 3790 PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure,
3905 PyObject **defs, int defcount, 3791 PyObject *name, PyObject *qualname)
3906 PyObject *kwdefs, PyObject *closure,
3907 PyObject *name, PyObject *qualname)
3908 { 3792 {
3909 PyCodeObject* co = (PyCodeObject*)_co; 3793 PyCodeObject* co = (PyCodeObject*)_co;
3910 PyFrameObject *f; 3794 PyFrameObject *f;
3911 PyObject *retval = NULL; 3795 PyObject *retval = NULL;
3912 PyObject **fastlocals, **freevars; 3796 PyObject **fastlocals, **freevars;
3913 PyThreadState *tstate; 3797 PyThreadState *tstate;
3914 PyObject *x, *u; 3798 PyObject *x, *u;
3915 const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount; 3799 const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount;
3916 Py_ssize_t i, n; 3800 Py_ssize_t i, n;
3917 PyObject *kwdict; 3801 PyObject *kwdict;
3918 3802
3919 assert((kwcount == 0) || (kws != NULL)); 3803 assert((kwcount == 0) || (kws != NULL));
3920 /* kws and kwargs are mutually exclusive
3921 (arbitrary limit to detect bugs) */
3922 assert(!((kws != NULL) && (kwargs != NULL)));
3923 3804
3924 if (globals == NULL) { 3805 if (globals == NULL) {
3925 PyErr_SetString(PyExc_SystemError, 3806 PyErr_SetString(PyExc_SystemError,
3926 "PyEval_EvalCodeEx: NULL globals"); 3807 "PyEval_EvalCodeEx: NULL globals");
3927 return NULL; 3808 return NULL;
3928 } 3809 }
3929 3810
3930 /* Create the frame */ 3811 /* Create the frame */
3931 tstate = PyThreadState_GET(); 3812 tstate = PyThreadState_GET();
3932 assert(tstate != NULL); 3813 assert(tstate != NULL);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
3990 PyErr_Format(PyExc_TypeError, 3871 PyErr_Format(PyExc_TypeError,
3991 "%U() keywords must be strings", 3872 "%U() keywords must be strings",
3992 co->co_name); 3873 co->co_name);
3993 goto fail; 3874 goto fail;
3994 } 3875 }
3995 3876
3996 /* Speed hack: do raw pointer compares. As names are 3877 /* Speed hack: do raw pointer compares. As names are
3997 normally interned this should almost always hit. */ 3878 normally interned this should almost always hit. */
3998 co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item; 3879 co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item;
3999 for (j = 0; j < total_args; j++) { 3880 for (j = 0; j < total_args; j++) {
4000 PyObject *name = co_varnames[j]; 3881 PyObject *nm = co_varnames[j];
4001 if (name == keyword) { 3882 if (nm == keyword)
4002 goto kw_found; 3883 goto kw_found;
4003 }
4004 } 3884 }
4005 3885
4006 /* Slow fallback, just in case */ 3886 /* Slow fallback, just in case */
4007 for (j = 0; j < total_args; j++) { 3887 for (j = 0; j < total_args; j++) {
4008 PyObject *name = co_varnames[j]; 3888 PyObject *nm = co_varnames[j];
4009 int cmp = PyObject_RichCompareBool(keyword, name, Py_EQ); 3889 int cmp = PyObject_RichCompareBool(
4010 if (cmp > 0) { 3890 keyword, nm, Py_EQ);
3891 if (cmp > 0)
4011 goto kw_found; 3892 goto kw_found;
4012 } 3893 else if (cmp < 0)
4013 else if (cmp < 0) {
4014 goto fail; 3894 goto fail;
4015 }
4016 } 3895 }
4017 3896
4018 if (j >= total_args && kwdict == NULL) { 3897 if (j >= total_args && kwdict == NULL) {
4019 PyErr_Format(PyExc_TypeError, 3898 PyErr_Format(PyExc_TypeError,
4020 "%U() got an unexpected keyword argument '%S'", 3899 "%U() got an unexpected "
4021 co->co_name, keyword); 3900 "keyword argument '%S'",
3901 co->co_name,
3902 keyword);
4022 goto fail; 3903 goto fail;
4023 } 3904 }
4024 3905
4025 if (PyDict_SetItem(kwdict, keyword, value) == -1) { 3906 if (PyDict_SetItem(kwdict, keyword, value) == -1) {
4026 goto fail; 3907 goto fail;
4027 } 3908 }
4028 continue; 3909 continue;
4029 3910
4030 kw_found: 3911 kw_found:
4031 if (GETLOCAL(j) != NULL) { 3912 if (GETLOCAL(j) != NULL) {
4032 PyErr_Format(PyExc_TypeError, 3913 PyErr_Format(PyExc_TypeError,
4033 "%U() got multiple values for argument '%S'", 3914 "%U() got multiple "
3915 "values for argument '%S'",
4034 co->co_name, 3916 co->co_name,
4035 keyword); 3917 keyword);
4036 goto fail; 3918 goto fail;
4037 } 3919 }
4038 Py_INCREF(value); 3920 Py_INCREF(value);
4039 SETLOCAL(j, value); 3921 SETLOCAL(j, value);
4040 }
4041
4042 /* Handle keyword arguments (passed as a dictionary) */
4043 if (kwargs != NULL && PyDict_Size(kwargs) != 0) {
4044 if (fastlocals_dict(fastlocals, co, kwdict, kwargs) < 0) {
4045 goto fail;
4046 }
4047 } 3922 }
4048 3923
4049 /* Check the number of positional arguments */ 3924 /* Check the number of positional arguments */
4050 if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) { 3925 if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) {
4051 too_many_positional(co, argcount, defcount, fastlocals); 3926 too_many_positional(co, argcount, defcount, fastlocals);
4052 goto fail; 3927 goto fail;
4053 } 3928 }
4054 3929
4055 /* Add missing positional arguments (copy default values from defs) */ 3930 /* Add missing positional arguments (copy default values from defs) */
4056 if (argcount < co->co_argcount) { 3931 if (argcount < co->co_argcount) {
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
4186 Py_DECREF(f); 4061 Py_DECREF(f);
4187 --tstate->recursion_depth; 4062 --tstate->recursion_depth;
4188 return retval; 4063 return retval;
4189 } 4064 }
4190 4065
4191 PyObject * 4066 PyObject *
4192 PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, 4067 PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
4193 PyObject **args, int argcount, PyObject **kws, int kwcount, 4068 PyObject **args, int argcount, PyObject **kws, int kwcount,
4194 PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure) 4069 PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure)
4195 { 4070 {
4196 return _PyEval_EvalCode(_co, globals, locals, 4071 return _PyEval_EvalCodeWithName(_co, globals, locals,
4197 args, argcount, 4072 args, argcount,
4198 kws, kwcount, NULL, 4073 kws, kwcount,
4199 defs, defcount, 4074 defs, defcount,
4200 kwdefs, closure, 4075 kwdefs, closure,
4201 NULL, NULL); 4076 NULL, NULL);
4202 } 4077 }
4203 4078
4204 static PyObject * 4079 static PyObject *
4205 special_lookup(PyObject *o, _Py_Identifier *id) 4080 special_lookup(PyObject *o, _Py_Identifier *id)
4206 { 4081 {
4207 PyObject *res; 4082 PyObject *res;
4208 res = _PyObject_LookupSpecial(o, id); 4083 res = _PyObject_LookupSpecial(o, id);
4209 if (res == NULL && !PyErr_Occurred()) { 4084 if (res == NULL && !PyErr_Occurred()) {
4210 PyErr_SetObject(PyExc_AttributeError, id->object); 4085 PyErr_SetObject(PyExc_AttributeError, id->object);
4211 return NULL; 4086 return NULL;
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after
4711 4586
4712 #ifdef Py_DEBUG 4587 #ifdef Py_DEBUG
4713 /* PyEval_CallObjectWithKeywords() must not be called with an exception 4588 /* PyEval_CallObjectWithKeywords() must not be called with an exception
4714 set. It raises a new exception if parameters are invalid or if 4589 set. It raises a new exception if parameters are invalid or if
4715 PyTuple_New() fails, and so the original exception is lost. */ 4590 PyTuple_New() fails, and so the original exception is lost. */
4716 assert(!PyErr_Occurred()); 4591 assert(!PyErr_Occurred());
4717 #endif 4592 #endif
4718 4593
4719 if (args == NULL) { 4594 if (args == NULL) {
4720 if (kwargs == NULL) { 4595 if (kwargs == NULL) {
4721 return _PyObject_FastCall(func, NULL, 0, 0); 4596 return _PyObject_CallNoArg(func);
4722 } 4597 }
4723 4598
4724 args = PyTuple_New(0); 4599 args = PyTuple_New(0);
4725 if (args == NULL) 4600 if (args == NULL)
4726 return NULL; 4601 return NULL;
4727 } 4602 }
4728 else if (!PyTuple_Check(args)) { 4603 else if (!PyTuple_Check(args)) {
4729 PyErr_SetString(PyExc_TypeError, 4604 PyErr_SetString(PyExc_TypeError,
4730 "argument list must be a tuple"); 4605 "argument list must be a tuple");
4731 return NULL; 4606 return NULL;
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
4999 qualname = ((PyFunctionObject *)func) -> func_qualname; 4874 qualname = ((PyFunctionObject *)func) -> func_qualname;
5000 4875
5001 if (argdefs != NULL) { 4876 if (argdefs != NULL) {
5002 d = &PyTuple_GET_ITEM(argdefs, 0); 4877 d = &PyTuple_GET_ITEM(argdefs, 0);
5003 nd = Py_SIZE(argdefs); 4878 nd = Py_SIZE(argdefs);
5004 } 4879 }
5005 else { 4880 else {
5006 d = NULL; 4881 d = NULL;
5007 nd = 0; 4882 nd = 0;
5008 } 4883 }
5009 return _PyEval_EvalCode((PyObject*)co, globals, (PyObject *)NULL, 4884 return _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
5010 stack, nargs, 4885 stack, nargs,
5011 stack + nargs, nk, NULL, 4886 stack + nargs, nk,
5012 d, nd, kwdefs, 4887 d, nd, kwdefs,
5013 closure, name, qualname); 4888 closure, name, qualname);
5014 } 4889 }
5015 4890
5016 PyObject * 4891 PyObject *
5017 _PyFunction_FastCall(PyObject *func, PyObject **args, int nargs, PyObject *kwarg s) 4892 _PyFunction_FastCall(PyObject *func, PyObject **args, int nargs, PyObject *kwarg s)
5018 { 4893 {
5019 PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); 4894 PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
5020 PyObject *globals = PyFunction_GET_GLOBALS(func); 4895 PyObject *globals = PyFunction_GET_GLOBALS(func);
5021 PyObject *argdefs = PyFunction_GET_DEFAULTS(func); 4896 PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
5022 PyObject *kwdefs, *closure, *name, *qualname; 4897 PyObject *kwdefs, *closure, *name, *qualname;
5023 PyObject **d; 4898 PyObject **d;
5024 int nd; 4899 int nd;
5025 4900
5026 PCALL(PCALL_FUNCTION); 4901 PCALL(PCALL_FUNCTION);
5027 PCALL(PCALL_FAST_FUNCTION); 4902 PCALL(PCALL_FAST_FUNCTION);
5028 4903
5029 assert(kwargs == NULL || PyDict_Check(kwargs)); 4904 /* issue #27128: support for keywords will come later */
5030 4905 assert(kwargs == NULL);
5031 if (co->co_kwonlyargcount == 0 && 4906
5032 (kwargs == NULL || PyDict_Size(kwargs) == 0) && 4907 if (co->co_kwonlyargcount == 0 && kwargs == NULL &&
5033 co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) 4908 co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
5034 { 4909 {
5035 if (argdefs == NULL && co->co_argcount == nargs) { 4910 if (argdefs == NULL && co->co_argcount == nargs) {
5036 return _PyFunction_FastCallNoKw(co, args, nargs, globals); 4911 return _PyFunction_FastCallNoKw(co, args, nargs, globals);
5037 } 4912 }
5038 else if (nargs == 0 && argdefs != NULL 4913 else if (nargs == 0 && argdefs != NULL
5039 && co->co_argcount == Py_SIZE(argdefs)) { 4914 && co->co_argcount == Py_SIZE(argdefs)) {
5040 /* function called with no arguments, but all parameters have 4915 /* function called with no arguments, but all parameters have
5041 a default value: use default values as arguments .*/ 4916 a default value: use default values as arguments .*/
5042 args = &PyTuple_GET_ITEM(argdefs, 0); 4917 args = &PyTuple_GET_ITEM(argdefs, 0);
5043 return _PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), 4918 return _PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs),
5044 globals); 4919 globals);
5045 } 4920 }
5046 } 4921 }
5047 4922
5048 kwdefs = PyFunction_GET_KW_DEFAULTS(func); 4923 kwdefs = PyFunction_GET_KW_DEFAULTS(func);
5049 closure = PyFunction_GET_CLOSURE(func); 4924 closure = PyFunction_GET_CLOSURE(func);
5050 name = ((PyFunctionObject *)func) -> func_name; 4925 name = ((PyFunctionObject *)func) -> func_name;
5051 qualname = ((PyFunctionObject *)func) -> func_qualname; 4926 qualname = ((PyFunctionObject *)func) -> func_qualname;
5052 4927
5053 if (argdefs != NULL) { 4928 if (argdefs != NULL) {
5054 d = &PyTuple_GET_ITEM(argdefs, 0); 4929 d = &PyTuple_GET_ITEM(argdefs, 0);
5055 nd = Py_SIZE(argdefs); 4930 nd = Py_SIZE(argdefs);
5056 } 4931 }
5057 else { 4932 else {
5058 d = NULL; 4933 d = NULL;
5059 nd = 0; 4934 nd = 0;
5060 } 4935 }
5061 return _PyEval_EvalCode((PyObject*)co, globals, (PyObject *)NULL, 4936 return _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
5062 args, nargs, 4937 args, nargs,
5063 NULL, 0, kwargs, 4938 NULL, 0,
5064 d, nd, kwdefs, 4939 d, nd, kwdefs,
5065 closure, name, qualname); 4940 closure, name, qualname);
5066 } 4941 }
5067 4942
5068 static PyObject * 4943 static PyObject *
5069 update_keyword_args(PyObject *orig_kwdict, int nk, PyObject ***pp_stack, 4944 update_keyword_args(PyObject *orig_kwdict, int nk, PyObject ***pp_stack,
5070 PyObject *func) 4945 PyObject *func)
5071 { 4946 {
5072 PyObject *kwdict = NULL; 4947 PyObject *kwdict = NULL;
5073 if (orig_kwdict == NULL) 4948 if (orig_kwdict == NULL)
5074 kwdict = PyDict_New(); 4949 kwdict = PyDict_New();
5075 else { 4950 else {
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
5416 return res; 5291 return res;
5417 } 5292 }
5418 5293
5419 Py_INCREF(import_func); 5294 Py_INCREF(import_func);
5420 5295
5421 stack[0] = name; 5296 stack[0] = name;
5422 stack[1] = f->f_globals; 5297 stack[1] = f->f_globals;
5423 stack[2] = f->f_locals == NULL ? Py_None : f->f_locals; 5298 stack[2] = f->f_locals == NULL ? Py_None : f->f_locals;
5424 stack[3] = fromlist; 5299 stack[3] = fromlist;
5425 stack[4] = level; 5300 stack[4] = level;
5426 res = _PyObject_FastCall(import_func, stack, 5, NULL); 5301 res = _PyObject_FastCall(import_func, stack, 5);
5427 Py_DECREF(import_func); 5302 Py_DECREF(import_func);
5428 return res; 5303 return res;
5429 } 5304 }
5430 5305
5431 static PyObject * 5306 static PyObject *
5432 import_from(PyObject *v, PyObject *name) 5307 import_from(PyObject *v, PyObject *name)
5433 { 5308 {
5434 PyObject *x; 5309 PyObject *x;
5435 _Py_IDENTIFIER(__name__); 5310 _Py_IDENTIFIER(__name__);
5436 PyObject *fullmodname, *pkgname; 5311 PyObject *fullmodname, *pkgname;
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
5649 Py_DECREF(l); 5524 Py_DECREF(l);
5650 return NULL; 5525 return NULL;
5651 } 5526 }
5652 PyList_SetItem(l, i, x); 5527 PyList_SetItem(l, i, x);
5653 } 5528 }
5654 return l; 5529 return l;
5655 #endif 5530 #endif
5656 } 5531 }
5657 5532
5658 #endif 5533 #endif
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+