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

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 2215 matching lines...) Expand 10 before | Expand all | Expand 10 after
2226 return result; 2226 return result;
2227 } 2227 }
2228 2228
2229 PyObject * 2229 PyObject *
2230 PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs) 2230 PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
2231 { 2231 {
2232 ternaryfunc call; 2232 ternaryfunc call;
2233 PyObject *result; 2233 PyObject *result;
2234 2234
2235 /* PyObject_Call() must not be called with an exception set, 2235 /* PyObject_Call() must not be called with an exception set,
2236 because it may clear it (directly or indirectly) and so the 2236 because it can clear it (directly or indirectly) and so the
2237 caller loses its exception */ 2237 caller loses its exception */
2238 assert(!PyErr_Occurred()); 2238 assert(!PyErr_Occurred());
2239 assert(PyTuple_Check(args)); 2239 assert(PyTuple_Check(args));
2240 assert(kwargs == NULL || PyDict_Check(kwargs)); 2240 assert(kwargs == NULL || PyDict_Check(kwargs));
2241 2241
2242 call = callable->ob_type->tp_call; 2242 call = callable->ob_type->tp_call;
2243 if (call == NULL) { 2243 if (call == NULL) {
2244 PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", 2244 PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
2245 callable->ob_type->tp_name); 2245 callable->ob_type->tp_name);
2246 return NULL; 2246 return NULL;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 12 matching lines...) Expand all
2312 } 2339 }
2313 2340
2314 PyObject * 2341 PyObject *
2315 _PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs, 2342 _PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs,
2316 PyObject *kwargs) 2343 PyObject *kwargs)
2317 { 2344 {
2318 ternaryfunc call; 2345 ternaryfunc call;
2319 PyObject *result = NULL; 2346 PyObject *result = NULL;
2320 2347
2321 /* _PyObject_FastCallDict() must not be called with an exception set, 2348 /* _PyObject_FastCallDict() must not be called with an exception set,
2322 because it may clear it (directly or indirectly) and so the 2349 because it can clear it (directly or indirectly) and so the
2323 caller loses its exception */ 2350 caller loses its exception */
2324 assert(!PyErr_Occurred()); 2351 assert(!PyErr_Occurred());
2325 2352
2326 assert(callable != NULL); 2353 assert(callable != NULL);
2327 assert(nargs >= 0); 2354 assert(nargs >= 0);
2328 assert(nargs == 0 || args != NULL); 2355 assert(nargs == 0 || args != NULL);
2329 assert(kwargs == NULL || PyDict_Check(kwargs)); 2356 assert(kwargs == NULL || PyDict_Check(kwargs));
2330 2357
2331 if (Py_EnterRecursiveCall(" while calling a Python object")) { 2358 if (Py_EnterRecursiveCall(" while calling a Python object")) {
2332 return NULL; 2359 return NULL;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
2442 stack[0] = obj; 2469 stack[0] = obj;
2443 memcpy(&stack[1], args, (alloc - 1) * sizeof(PyObject *)); 2470 memcpy(&stack[1], args, (alloc - 1) * sizeof(PyObject *));
2444 2471
2445 result = _PyObject_FastCallKeywords(func, 2472 result = _PyObject_FastCallKeywords(func,
2446 stack, nargs + 1, 2473 stack, nargs + 1,
2447 kwnames); 2474 kwnames);
2448 if (stack != small_stack) { 2475 if (stack != small_stack) {
2449 PyMem_Free(stack); 2476 PyMem_Free(stack);
2450 } 2477 }
2451 2478
2452 result = _Py_CheckFunctionResult(func, result, NULL);
2453 return result; 2479 return result;
2454 } 2480 }
2455 2481
2456 PyObject * 2482 PyObject *
2457 _PyStack_AsDict(PyObject **values, PyObject *kwnames) 2483 _PyStack_AsDict(PyObject **values, PyObject *kwnames)
2458 { 2484 {
2459 Py_ssize_t nkwargs = PyTuple_GET_SIZE(kwnames); 2485 Py_ssize_t nkwargs;
2460 PyObject *kwdict; 2486 PyObject *kwdict;
2461 Py_ssize_t i; 2487 Py_ssize_t i;
2462 2488
2489 assert(kwnames != NULL);
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 _PyStack_UnpackDict(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);
(...skipping 49 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());
2578 assert(fastcall != NULL);
2579 assert(kwargs == NULL || PyDict_Check(kwargs));
2551 2580
2552 if (_PyStack_UnpackDict(args, nargs, kwargs, &stack, &kwnames) < 0) { 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 return result; 2590 return result;
2563 } 2591 }
2564 2592
2565 PyObject * 2593 PyObject *
2566 _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg s, 2594 _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg s,
2567 PyObject *kwnames) 2595 PyObject *kwnames)
2568 { 2596 {
2597 /* _PyObject_FastCallKeywords() must not be called with an exception set,
2598 because it can clear it (directly or indirectly) and so the
2599 caller loses its exception */
2600 assert(!PyErr_Occurred());
2601
2569 assert(nargs >= 0); 2602 assert(nargs >= 0);
2570 assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); 2603 assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
2571 2604
2572 /* 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
2573 be unique: these checks are implemented in Python/ceval.c and 2606 be unique: these checks are implemented in Python/ceval.c and
2574 _PyArg_ParseStackAndKeywords(). */ 2607 _PyArg_ParseStackAndKeywords(). */
2575 2608
2576 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
2577 return _PyFunction_FastCallKeywords(callable, stack, nargs, kwnames); 2611 return _PyFunction_FastCallKeywords(callable, stack, nargs, kwnames);
2578 } 2612 }
2579 if (PyCFunction_Check(callable)) { 2613 if (PyCFunction_Check(callable)) {
2580 return _PyCFunction_FastCallKeywords(callable, stack, nargs, kwnames); 2614 return _PyCFunction_FastCallKeywords(callable, stack, nargs, kwnames);
2581 } 2615 }
2582 else if (PyType_HasFeature(Py_TYPE(callable), Py_TPFLAGS_HAVE_FASTCALL) 2616 else if (PyType_HasFeature(Py_TYPE(callable), Py_TPFLAGS_HAVE_FASTCALL)
2583 && Py_TYPE(callable)->tp_fastcall) { 2617 && Py_TYPE(callable)->tp_fastcall) {
2584 fastternaryfunc fastcall = Py_TYPE(callable)->tp_fastcall; 2618 fastternaryfunc fastcall = Py_TYPE(callable)->tp_fastcall;
2585 PyObject *result; 2619 PyObject *result;
2586 2620
(...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after
3346 /* Free's a NULL terminated char** array of C strings. */ 3380 /* Free's a NULL terminated char** array of C strings. */
3347 void 3381 void
3348 _Py_FreeCharPArray(char *const array[]) 3382 _Py_FreeCharPArray(char *const array[])
3349 { 3383 {
3350 Py_ssize_t i; 3384 Py_ssize_t i;
3351 for (i = 0; array[i] != NULL; ++i) { 3385 for (i = 0; array[i] != NULL; ++i) {
3352 PyMem_Free(array[i]); 3386 PyMem_Free(array[i]);
3353 } 3387 }
3354 PyMem_Free((void*)array); 3388 PyMem_Free((void*)array);
3355 } 3389 }
LEFTRIGHT

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