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

Delta Between Two Patch Sets: Objects/abstract.c

Issue 29259: Add tp_fastcall to PyTypeObject: support FASTCALL calling convention for all callable objects
Left Patch Set: Created 3 years, 1 month ago
Right Patch Set: Created 3 years 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
LEFTRIGHT
1 /* Abstract Object Interface (many thanks to Jim Fulton) */ 1 /* Abstract Object Interface (many thanks to Jim Fulton) */
2 2
3 #include "Python.h" 3 #include "Python.h"
4 #include <ctype.h> 4 #include <ctype.h>
5 #include "structmember.h" /* we need the offsetof() macro from there */ 5 #include "structmember.h" /* we need the offsetof() macro from there */
6 #include "longintrepr.h" 6 #include "longintrepr.h"
7 7
8 8
9 9
10 /* Shorthands to return certain errors */ 10 /* Shorthands to return certain errors */
(...skipping 2234 matching lines...) Expand 10 before | Expand all | Expand 10 after
2245 callable->ob_type->tp_name); 2245 callable->ob_type->tp_name);
2246 return NULL; 2246 return NULL;
2247 } 2247 }
2248 2248
2249 if (Py_EnterRecursiveCall(" while calling a Python object")) 2249 if (Py_EnterRecursiveCall(" while calling a Python object"))
2250 return NULL; 2250 return NULL;
2251 2251
2252 if (PyType_HasFeature(Py_TYPE(callable), Py_TPFLAGS_HAVE_FASTCALL) 2252 if (PyType_HasFeature(Py_TYPE(callable), Py_TPFLAGS_HAVE_FASTCALL)
2253 && Py_TYPE(callable)->tp_fastcall) { 2253 && Py_TYPE(callable)->tp_fastcall) {
2254 result = _Py_RawFastCallDict(callable, 2254 result = _Py_RawFastCallDict(callable,
2255 Py_TYPE(callable)->tp_fastcall, 2255 Py_TYPE(callable)->tp_fastcall,
2256 &PyTuple_GET_ITEM(args, 0), 2256 &PyTuple_GET_ITEM(args, 0),
2257 PyTuple_GET_SIZE(args), 2257 PyTuple_GET_SIZE(args),
2258 kwargs); 2258 kwargs);
2259 } 2259 }
2260 else { 2260 else {
2261 result = (*call)(callable, args, kwargs); 2261 result = (*call)(callable, args, kwargs);
2262 } 2262 }
2263 2263
2264 Py_LeaveRecursiveCall(); 2264 Py_LeaveRecursiveCall();
2265 2265
2266 return _Py_CheckFunctionResult(callable, result, NULL); 2266 return _Py_CheckFunctionResult(callable, result, NULL);
2267 } 2267 }
2268 2268
(...skipping 11 matching lines...) Expand all
2280 } 2280 }
2281 2281
2282 for (i=0; i < nargs; i++) { 2282 for (i=0; i < nargs; i++) {
2283 PyObject *item = stack[i]; 2283 PyObject *item = stack[i];
2284 Py_INCREF(item); 2284 Py_INCREF(item);
2285 PyTuple_SET_ITEM(args, i, item); 2285 PyTuple_SET_ITEM(args, i, item);
2286 } 2286 }
2287 return args; 2287 return args;
2288 } 2288 }
2289 2289
2290 int _Py_NO_INLINE
haypo 2017/01/26 03:35:21 Not sure if _Py_NO_INLINE is needed here.
2291 _PyStack_AsTupleAndDict(PyObject **stack, Py_ssize_t nargs, PyObject *kwnames,
2292 PyObject **p_args, PyObject **p_kwargs)
2293 {
2294 PyObject *args, *kwargs;
2295
2296 args = _PyStack_AsTuple(stack, nargs);
2297 if (args == NULL) {
2298 return -1;
2299 }
2300
2301 if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) != 0) {
2302 kwargs = _PyStack_AsDict(stack + nargs, kwnames);
2303 if (kwargs == NULL) {
2304 Py_DECREF(args);
2305 return -1;
2306 }
2307 }
2308 else {
2309 kwargs = NULL;
2310 }
2311
2312 *p_args = args;
2313 *p_kwargs = kwargs;
2314 return 0;
2315 }
2316
2290 PyObject* 2317 PyObject*
2291 _PyStack_AsTupleSlice(PyObject **stack, Py_ssize_t nargs, 2318 _PyStack_AsTupleSlice(PyObject **stack, Py_ssize_t nargs,
2292 Py_ssize_t start, Py_ssize_t end) 2319 Py_ssize_t start, Py_ssize_t end)
2293 { 2320 {
2294 PyObject *args; 2321 PyObject *args;
2295 Py_ssize_t i; 2322 Py_ssize_t i;
2296 2323
2297 assert(0 <= start); 2324 assert(0 <= start);
2298 assert(end <= nargs); 2325 assert(end <= nargs);
2299 assert(start <= end); 2326 assert(start <= end);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2336 result = _PyFunction_FastCallDict(callable, args, nargs, kwargs); 2363 result = _PyFunction_FastCallDict(callable, args, nargs, kwargs);
2337 } 2364 }
2338 else if (PyCFunction_Check(callable)) { 2365 else if (PyCFunction_Check(callable)) {
2339 result = _PyCFunction_FastCallDict(callable, args, nargs, kwargs); 2366 result = _PyCFunction_FastCallDict(callable, args, nargs, kwargs);
2340 } 2367 }
2341 else if (PyType_HasFeature(Py_TYPE(callable), Py_TPFLAGS_HAVE_FASTCALL) 2368 else if (PyType_HasFeature(Py_TYPE(callable), Py_TPFLAGS_HAVE_FASTCALL)
2342 && Py_TYPE(callable)->tp_fastcall) { 2369 && Py_TYPE(callable)->tp_fastcall) {
2343 fastternaryfunc fastcall = Py_TYPE(callable)->tp_fastcall; 2370 fastternaryfunc fastcall = Py_TYPE(callable)->tp_fastcall;
2344 2371
2345 result = _Py_RawFastCallDict(callable, fastcall, args, nargs, kwargs); 2372 result = _Py_RawFastCallDict(callable, fastcall, args, nargs, kwargs);
2373 result = _Py_CheckFunctionResult(callable, result, NULL);
2346 } 2374 }
2347 else { 2375 else {
2348 PyObject *tuple; 2376 PyObject *tuple;
2349 2377
2350 /* Slow-path: build a temporary tuple */ 2378 /* Slow-path: build a temporary tuple */
2351 call = Py_TYPE(callable)->tp_call; 2379 call = Py_TYPE(callable)->tp_call;
2352 if (call == NULL) { 2380 if (call == NULL) {
2353 PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", 2381 PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
2354 callable->ob_type->tp_name); 2382 callable->ob_type->tp_name);
2355 goto exit; 2383 goto exit;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
2461 assert(kwnames != NULL); 2489 assert(kwnames != NULL);
2462 nkwargs = PyTuple_GET_SIZE(kwnames); 2490 nkwargs = PyTuple_GET_SIZE(kwnames);
2463 kwdict = _PyDict_NewPresized(nkwargs); 2491 kwdict = _PyDict_NewPresized(nkwargs);
2464 if (kwdict == NULL) { 2492 if (kwdict == NULL) {
2465 return NULL; 2493 return NULL;
2466 } 2494 }
2467 2495
2468 for (i = 0; i < nkwargs; i++) { 2496 for (i = 0; i < nkwargs; i++) {
2469 PyObject *key = PyTuple_GET_ITEM(kwnames, i); 2497 PyObject *key = PyTuple_GET_ITEM(kwnames, i);
2470 PyObject *value = *values++; 2498 PyObject *value = *values++;
2471 assert(PyUnicode_CheckExact(key)); 2499 /* If key already exists, replace it with the new value */
2472 assert(PyDict_GetItem(kwdict, key) == NULL);
2473 if (PyDict_SetItem(kwdict, key, value)) { 2500 if (PyDict_SetItem(kwdict, key, value)) {
2474 Py_DECREF(kwdict); 2501 Py_DECREF(kwdict);
2475 return NULL; 2502 return NULL;
2476 } 2503 }
2477 } 2504 }
2478 return kwdict; 2505 return kwdict;
2479 } 2506 }
2480 2507
2481 static int 2508 int
2482 stack_unpack_dict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs, 2509 _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
2483 PyObject ***p_stack, PyObject **p_kwnames) 2510 PyObject ***p_stack, PyObject **p_kwnames)
2484 { 2511 {
2485 PyObject **stack, **kwstack; 2512 PyObject **stack, **kwstack;
2486 Py_ssize_t nkwargs; 2513 Py_ssize_t nkwargs;
2487 Py_ssize_t pos, i; 2514 Py_ssize_t pos, i;
2488 PyObject *key, *value; 2515 PyObject *key, *value;
2489 PyObject *kwnames; 2516 PyObject *kwnames;
2490 2517
2491 assert(nargs >= 0); 2518 assert(nargs >= 0);
2492 assert(kwargs == NULL || PyDict_CheckExact(kwargs)); 2519 assert(kwargs == NULL || PyDict_CheckExact(kwargs));
2493 2520
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2541 2568
2542 PyObject * 2569 PyObject *
2543 _Py_RawFastCallDict(PyObject *self, fastternaryfunc fastcall, 2570 _Py_RawFastCallDict(PyObject *self, fastternaryfunc fastcall,
2544 PyObject **args, Py_ssize_t nargs, PyObject *kwargs) 2571 PyObject **args, Py_ssize_t nargs, PyObject *kwargs)
2545 { 2572 {
2546 PyObject **stack; 2573 PyObject **stack;
2547 PyObject *kwnames; 2574 PyObject *kwnames;
2548 PyObject *result; 2575 PyObject *result;
2549 2576
2550 assert(!PyErr_Occurred()); 2577 assert(!PyErr_Occurred());
2551 2578 assert(fastcall != NULL);
2552 if (stack_unpack_dict(args, nargs, kwargs, &stack, &kwnames) < 0) { 2579 assert(kwargs == NULL || PyDict_Check(kwargs));
2580
2581 if (_PyStack_UnpackDict(args, nargs, kwargs, &stack, &kwnames) < 0) {
2553 return NULL; 2582 return NULL;
2554 } 2583 }
2555 2584
2556 result = fastcall(self, stack, nargs, kwnames); 2585 result = fastcall(self, stack, nargs, kwnames);
2557 if (stack != args) { 2586 if (stack != args) {
2558 PyMem_Free(stack); 2587 PyMem_Free(stack);
2559 } 2588 }
2560 Py_XDECREF(kwnames); 2589 Py_XDECREF(kwnames);
2561
2562 result = _Py_CheckFunctionResult(self, result, NULL);
2563 return result; 2590 return result;
2564 } 2591 }
2565 2592
2566 PyObject * 2593 PyObject *
2567 _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg s, 2594 _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg s,
2568 PyObject *kwnames) 2595 PyObject *kwnames)
2569 { 2596 {
2570 /* _PyObject_FastCallKeywords() must not be called with an exception set, 2597 /* _PyObject_FastCallKeywords() must not be called with an exception set,
2571 because it can clear it (directly or indirectly) and so the 2598 because it can clear it (directly or indirectly) and so the
2572 caller loses its exception */ 2599 caller loses its exception */
2573 assert(!PyErr_Occurred()); 2600 assert(!PyErr_Occurred());
2574 2601
2575 assert(nargs >= 0); 2602 assert(nargs >= 0);
2576 assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); 2603 assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
2577 2604
2578 /* kwnames must only contains str strings, no subclass, and all keys must 2605 /* kwnames must only contains str strings, no subclass, and all keys must
2579 be unique: these checks are implemented in Python/ceval.c and 2606 be unique: these checks are implemented in Python/ceval.c and
2580 _PyArg_ParseStackAndKeywords(). */ 2607 _PyArg_ParseStackAndKeywords(). */
2581 2608
2582 if (PyFunction_Check(callable)) { 2609 if (PyFunction_Check(callable)) {
2610 /* FIXME: should we use Py_EnterRecursiveCall() here? */
haypo 2017/01/26 03:35:21 The FIXME can be removed, the issue is now tracked
2583 return _PyFunction_FastCallKeywords(callable, stack, nargs, kwnames); 2611 return _PyFunction_FastCallKeywords(callable, stack, nargs, kwnames);
2584 } 2612 }
2585 if (PyCFunction_Check(callable)) { 2613 if (PyCFunction_Check(callable)) {
2586 return _PyCFunction_FastCallKeywords(callable, stack, nargs, kwnames); 2614 return _PyCFunction_FastCallKeywords(callable, stack, nargs, kwnames);
2587 } 2615 }
2588 else if (PyType_HasFeature(Py_TYPE(callable), Py_TPFLAGS_HAVE_FASTCALL) 2616 else if (PyType_HasFeature(Py_TYPE(callable), Py_TPFLAGS_HAVE_FASTCALL)
2589 && Py_TYPE(callable)->tp_fastcall) { 2617 && Py_TYPE(callable)->tp_fastcall) {
2590 fastternaryfunc fastcall = Py_TYPE(callable)->tp_fastcall; 2618 fastternaryfunc fastcall = Py_TYPE(callable)->tp_fastcall;
2591 PyObject *result; 2619 PyObject *result;
2592 2620
(...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after
3352 /* Free's a NULL terminated char** array of C strings. */ 3380 /* Free's a NULL terminated char** array of C strings. */
3353 void 3381 void
3354 _Py_FreeCharPArray(char *const array[]) 3382 _Py_FreeCharPArray(char *const array[])
3355 { 3383 {
3356 Py_ssize_t i; 3384 Py_ssize_t i;
3357 for (i = 0; array[i] != NULL; ++i) { 3385 for (i = 0; array[i] != NULL; ++i) {
3358 PyMem_Free(array[i]); 3386 PyMem_Free(array[i]);
3359 } 3387 }
3360 PyMem_Free((void*)array); 3388 PyMem_Free((void*)array);
3361 } 3389 }
LEFTRIGHT

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