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

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, 2 months ago
Right Patch Set: Created 3 years, 2 months 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;
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 result = (*call)(callable, args, kwargs); 2252 if (PyType_HasFeature(Py_TYPE(callable), Py_TPFLAGS_HAVE_FASTCALL)
2253 && Py_TYPE(callable)->tp_fastcall) {
2254 result = _Py_RawFastCallDict(callable,
2255 Py_TYPE(callable)->tp_fastcall,
2256 &PyTuple_GET_ITEM(args, 0),
2257 PyTuple_GET_SIZE(args),
2258 kwargs);
2259 }
2260 else {
2261 result = (*call)(callable, args, kwargs);
2262 }
2253 2263
2254 Py_LeaveRecursiveCall(); 2264 Py_LeaveRecursiveCall();
2255 2265
2256 return _Py_CheckFunctionResult(callable, result, NULL); 2266 return _Py_CheckFunctionResult(callable, result, NULL);
2257 } 2267 }
2258 2268
2259 /* Issue #29234: Inlining _PyStack_AsTuple() into callers increases their 2269 /* Issue #29234: Inlining _PyStack_AsTuple() into callers increases their
2260 stack consumption, Disable inlining to optimize the stack consumption. */ 2270 stack consumption, Disable inlining to optimize the stack consumption. */
2261 PyObject* _Py_NO_INLINE 2271 PyObject* _Py_NO_INLINE
2262 _PyStack_AsTuple(PyObject **stack, Py_ssize_t nargs) 2272 _PyStack_AsTuple(PyObject **stack, Py_ssize_t nargs)
2263 { 2273 {
2264 PyObject *args; 2274 PyObject *args;
2265 Py_ssize_t i; 2275 Py_ssize_t i;
2266 2276
2267 args = PyTuple_New(nargs); 2277 args = PyTuple_New(nargs);
2268 if (args == NULL) { 2278 if (args == NULL) {
2269 return NULL; 2279 return NULL;
2270 } 2280 }
2271 2281
2272 for (i=0; i < nargs; i++) { 2282 for (i=0; i < nargs; i++) {
2273 PyObject *item = stack[i]; 2283 PyObject *item = stack[i];
2274 Py_INCREF(item); 2284 Py_INCREF(item);
2275 PyTuple_SET_ITEM(args, i, item); 2285 PyTuple_SET_ITEM(args, i, item);
2276 } 2286 }
2277 return args; 2287 return args;
2278 } 2288 }
2279 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
2280 PyObject* 2317 PyObject*
2281 _PyStack_AsTupleSlice(PyObject **stack, Py_ssize_t nargs, 2318 _PyStack_AsTupleSlice(PyObject **stack, Py_ssize_t nargs,
2282 Py_ssize_t start, Py_ssize_t end) 2319 Py_ssize_t start, Py_ssize_t end)
2283 { 2320 {
2284 PyObject *args; 2321 PyObject *args;
2285 Py_ssize_t i; 2322 Py_ssize_t i;
2286 2323
2287 assert(0 <= start); 2324 assert(0 <= start);
2288 assert(end <= nargs); 2325 assert(end <= nargs);
2289 assert(start <= end); 2326 assert(start <= end);
(...skipping 12 matching lines...) Expand all
2302 } 2339 }
2303 2340
2304 PyObject * 2341 PyObject *
2305 _PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs, 2342 _PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs,
2306 PyObject *kwargs) 2343 PyObject *kwargs)
2307 { 2344 {
2308 ternaryfunc call; 2345 ternaryfunc call;
2309 PyObject *result = NULL; 2346 PyObject *result = NULL;
2310 2347
2311 /* _PyObject_FastCallDict() must not be called with an exception set, 2348 /* _PyObject_FastCallDict() must not be called with an exception set,
2312 because it may clear it (directly or indirectly) and so the 2349 because it can clear it (directly or indirectly) and so the
2313 caller loses its exception */ 2350 caller loses its exception */
2314 assert(!PyErr_Occurred()); 2351 assert(!PyErr_Occurred());
2315 2352
2316 assert(callable != NULL); 2353 assert(callable != NULL);
2317 assert(nargs >= 0); 2354 assert(nargs >= 0);
2318 assert(nargs == 0 || args != NULL); 2355 assert(nargs == 0 || args != NULL);
2319 assert(kwargs == NULL || PyDict_Check(kwargs)); 2356 assert(kwargs == NULL || PyDict_Check(kwargs));
2320 2357
2321 if (Py_EnterRecursiveCall(" while calling a Python object")) { 2358 if (Py_EnterRecursiveCall(" while calling a Python object")) {
2322 return NULL; 2359 return NULL;
2323 } 2360 }
2324 2361
2325 if (PyFunction_Check(callable)) { 2362 if (PyFunction_Check(callable)) {
2326 result = _PyFunction_FastCallDict(callable, args, nargs, kwargs); 2363 result = _PyFunction_FastCallDict(callable, args, nargs, kwargs);
2327 } 2364 }
2328 else if (PyCFunction_Check(callable)) { 2365 else if (PyCFunction_Check(callable)) {
2329 result = _PyCFunction_FastCallDict(callable, args, nargs, kwargs); 2366 result = _PyCFunction_FastCallDict(callable, args, nargs, kwargs);
2330 } 2367 }
2331 /* FIXME: should we avoid tp_fastcall if tp_call is not fastcall_wrapper? */ 2368 else if (PyType_HasFeature(Py_TYPE(callable), Py_TPFLAGS_HAVE_FASTCALL)
2332 else if (_Py_TYPE_HAS_FASTCALL(Py_TYPE(callable))) { 2369 && Py_TYPE(callable)->tp_fastcall) {
2333 fastternaryfunc fastcall = Py_TYPE(callable)->tp_fastcall; 2370 fastternaryfunc fastcall = Py_TYPE(callable)->tp_fastcall;
2334 2371
2335 result = _Py_FastCall_FromArgs(callable, fastcall, args, nargs, kwargs); 2372 result = _Py_RawFastCallDict(callable, fastcall, args, nargs, kwargs);
2373 result = _Py_CheckFunctionResult(callable, result, NULL);
2336 } 2374 }
2337 else { 2375 else {
2338 PyObject *tuple; 2376 PyObject *tuple;
2339 2377
2340 /* Slow-path: build a temporary tuple */ 2378 /* Slow-path: build a temporary tuple */
2341 call = Py_TYPE(callable)->tp_call; 2379 call = Py_TYPE(callable)->tp_call;
2342 if (call == NULL) { 2380 if (call == NULL) {
2343 PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", 2381 PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
2344 callable->ob_type->tp_name); 2382 callable->ob_type->tp_name);
2345 goto exit; 2383 goto exit;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
2431 stack[0] = obj; 2469 stack[0] = obj;
2432 memcpy(&stack[1], args, (alloc - 1) * sizeof(PyObject *)); 2470 memcpy(&stack[1], args, (alloc - 1) * sizeof(PyObject *));
2433 2471
2434 result = _PyObject_FastCallKeywords(func, 2472 result = _PyObject_FastCallKeywords(func,
2435 stack, nargs + 1, 2473 stack, nargs + 1,
2436 kwnames); 2474 kwnames);
2437 if (stack != small_stack) { 2475 if (stack != small_stack) {
2438 PyMem_Free(stack); 2476 PyMem_Free(stack);
2439 } 2477 }
2440 2478
2441 result = _Py_CheckFunctionResult(func, result, NULL);
2442 return result; 2479 return result;
2443 } 2480 }
2444 2481
2445 PyObject * 2482 PyObject *
2446 _PyStack_AsDict(PyObject **values, PyObject *kwnames) 2483 _PyStack_AsDict(PyObject **values, PyObject *kwnames)
2447 { 2484 {
2448 Py_ssize_t nkwargs = PyTuple_GET_SIZE(kwnames); 2485 Py_ssize_t nkwargs;
2449 PyObject *kwdict; 2486 PyObject *kwdict;
2450 Py_ssize_t i; 2487 Py_ssize_t i;
2451 2488
2489 assert(kwnames != NULL);
2490 nkwargs = PyTuple_GET_SIZE(kwnames);
2452 kwdict = _PyDict_NewPresized(nkwargs); 2491 kwdict = _PyDict_NewPresized(nkwargs);
2453 if (kwdict == NULL) { 2492 if (kwdict == NULL) {
2454 return NULL; 2493 return NULL;
2455 } 2494 }
2456 2495
2457 for (i = 0; i < nkwargs; i++) { 2496 for (i = 0; i < nkwargs; i++) {
2458 PyObject *key = PyTuple_GET_ITEM(kwnames, i); 2497 PyObject *key = PyTuple_GET_ITEM(kwnames, i);
2459 PyObject *value = *values++; 2498 PyObject *value = *values++;
2460 assert(PyUnicode_CheckExact(key)); 2499 /* If key already exists, replace it with the new value */
2461 assert(PyDict_GetItem(kwdict, key) == NULL);
2462 if (PyDict_SetItem(kwdict, key, value)) { 2500 if (PyDict_SetItem(kwdict, key, value)) {
2463 Py_DECREF(kwdict); 2501 Py_DECREF(kwdict);
2464 return NULL; 2502 return NULL;
2465 } 2503 }
2466 } 2504 }
2467 return kwdict; 2505 return kwdict;
2468 } 2506 }
2469 2507
2470 static int 2508 int
2471 _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs, 2509 _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
2472 PyObject ***p_stack, PyObject **p_kwnames) 2510 PyObject ***p_stack, PyObject **p_kwnames)
2473 { 2511 {
2474 PyObject **stack, **kwstack; 2512 PyObject **stack, **kwstack;
2475 Py_ssize_t nkwargs; 2513 Py_ssize_t nkwargs;
2476 Py_ssize_t pos, i; 2514 Py_ssize_t pos, i;
2477 PyObject *key, *value; 2515 PyObject *key, *value;
2478 PyObject *kwnames; 2516 PyObject *kwnames;
2479 2517
2480 assert(nargs >= 0); 2518 assert(nargs >= 0);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2522 kwstack[i] = value; 2560 kwstack[i] = value;
2523 i++; 2561 i++;
2524 } 2562 }
2525 2563
2526 *p_stack = stack; 2564 *p_stack = stack;
2527 *p_kwnames = kwnames; 2565 *p_kwnames = kwnames;
2528 return 0; 2566 return 0;
2529 } 2567 }
2530 2568
2531 PyObject * 2569 PyObject *
2532 _Py_FastCall_FromArgs(PyObject *self, fastternaryfunc fastcall, 2570 _Py_RawFastCallDict(PyObject *self, fastternaryfunc fastcall,
2533 PyObject **args, Py_ssize_t nargs, PyObject *kwargs) 2571 PyObject **args, Py_ssize_t nargs, PyObject *kwargs)
2534 { 2572 {
2535 PyObject **stack; 2573 PyObject **stack;
2536 PyObject *kwnames; 2574 PyObject *kwnames;
2537 PyObject *result; 2575 PyObject *result;
2538 2576
2539 assert(!PyErr_Occurred()); 2577 assert(!PyErr_Occurred());
2578 assert(fastcall != NULL);
2579 assert(kwargs == NULL || PyDict_Check(kwargs));
2540 2580
2541 if (_PyStack_UnpackDict(args, nargs, kwargs, &stack, &kwnames) < 0) { 2581 if (_PyStack_UnpackDict(args, nargs, kwargs, &stack, &kwnames) < 0) {
2542 return NULL; 2582 return NULL;
2543 } 2583 }
2544 2584
2545 result = fastcall(self, stack, nargs, kwnames); 2585 result = fastcall(self, stack, nargs, kwnames);
2546 if (stack != args) { 2586 if (stack != args) {
2547 PyMem_Free(stack); 2587 PyMem_Free(stack);
2548 } 2588 }
2549 Py_XDECREF(kwnames); 2589 Py_XDECREF(kwnames);
2550
2551 result = _Py_CheckFunctionResult(self, result, NULL);
2552 return result; 2590 return result;
2553 } 2591 }
2554 2592
2555 PyObject * 2593 PyObject *
2556 _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg s, 2594 _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg s,
2557 PyObject *kwnames) 2595 PyObject *kwnames)
2558 { 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
2559 assert(nargs >= 0); 2602 assert(nargs >= 0);
2560 assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); 2603 assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
2561 2604
2562 /* 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
2563 be unique: these checks are implemented in Python/ceval.c and 2606 be unique: these checks are implemented in Python/ceval.c and
2564 _PyArg_ParseStackAndKeywords(). */ 2607 _PyArg_ParseStackAndKeywords(). */
2565 2608
2566 if (PyFunction_Check(callable)) { 2609 if (PyFunction_Check(callable)) {
2567 /* FIXME: should we use Py_EnterRecursiveCall() here? */ 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
2568 return _PyFunction_FastCallKeywords(callable, stack, nargs, kwnames); 2611 return _PyFunction_FastCallKeywords(callable, stack, nargs, kwnames);
2569 } 2612 }
2570 if (PyCFunction_Check(callable)) { 2613 if (PyCFunction_Check(callable)) {
2571 return _PyCFunction_FastCallKeywords(callable, stack, nargs, kwnames); 2614 return _PyCFunction_FastCallKeywords(callable, stack, nargs, kwnames);
2572 } 2615 }
2573 else if (_Py_TYPE_HAS_FASTCALL(Py_TYPE(callable))) { 2616 else if (PyType_HasFeature(Py_TYPE(callable), Py_TPFLAGS_HAVE_FASTCALL)
2617 && Py_TYPE(callable)->tp_fastcall) {
2574 fastternaryfunc fastcall = Py_TYPE(callable)->tp_fastcall; 2618 fastternaryfunc fastcall = Py_TYPE(callable)->tp_fastcall;
2575 PyObject *result; 2619 PyObject *result;
2576 2620
2577 if (Py_EnterRecursiveCall(" while calling a Python object")) { 2621 if (Py_EnterRecursiveCall(" while calling a Python object")) {
2578 return NULL; 2622 return NULL;
2579 } 2623 }
2580 2624
2581 result = fastcall(callable, stack, nargs, kwnames); 2625 result = fastcall(callable, stack, nargs, kwnames);
2582 result = _Py_CheckFunctionResult(callable, result, NULL); 2626 result = _Py_CheckFunctionResult(callable, result, NULL);
2583 2627
(...skipping 752 matching lines...) Expand 10 before | Expand all | Expand 10 after
3336 /* Free's a NULL terminated char** array of C strings. */ 3380 /* Free's a NULL terminated char** array of C strings. */
3337 void 3381 void
3338 _Py_FreeCharPArray(char *const array[]) 3382 _Py_FreeCharPArray(char *const array[])
3339 { 3383 {
3340 Py_ssize_t i; 3384 Py_ssize_t i;
3341 for (i = 0; array[i] != NULL; ++i) { 3385 for (i = 0; array[i] != NULL; ++i) {
3342 PyMem_Free(array[i]); 3386 PyMem_Free(array[i]);
3343 } 3387 }
3344 PyMem_Free((void*)array); 3388 PyMem_Free((void*)array);
3345 } 3389 }
LEFTRIGHT

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