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

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;
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 2287 return args;
2288 }
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
2317 PyObject*
2318 _PyStack_AsTupleSlice(PyObject **stack, Py_ssize_t nargs,
2319 Py_ssize_t start, Py_ssize_t end)
2320 {
2321 PyObject *args;
2322 Py_ssize_t i;
2323
2324 assert(0 <= start);
2325 assert(end <= nargs);
2326 assert(start <= end);
2327
2328 args = PyTuple_New(end - start);
2329 if (args == NULL) {
2330 return NULL;
2331 }
2332
2333 for (i=start; i < end; i++) {
2334 PyObject *item = stack[i];
2335 Py_INCREF(item);
2336 PyTuple_SET_ITEM(args, i - start, item);
2337 }
2278 return args; 2338 return args;
2279 } 2339 }
2280 2340
2281 PyObject * 2341 PyObject *
2282 _PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs, 2342 _PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs,
2283 PyObject *kwargs) 2343 PyObject *kwargs)
2284 { 2344 {
2285 ternaryfunc call; 2345 ternaryfunc call;
2286 PyObject *result = NULL; 2346 PyObject *result = NULL;
2287 2347
2288 /* _PyObject_FastCallDict() must not be called with an exception set, 2348 /* _PyObject_FastCallDict() must not be called with an exception set,
2289 because it may clear it (directly or indirectly) and so the 2349 because it can clear it (directly or indirectly) and so the
2290 caller loses its exception */ 2350 caller loses its exception */
2291 assert(!PyErr_Occurred()); 2351 assert(!PyErr_Occurred());
2292 2352
2293 assert(callable != NULL); 2353 assert(callable != NULL);
2294 assert(nargs >= 0); 2354 assert(nargs >= 0);
2295 assert(nargs == 0 || args != NULL); 2355 assert(nargs == 0 || args != NULL);
2296 assert(kwargs == NULL || PyDict_Check(kwargs)); 2356 assert(kwargs == NULL || PyDict_Check(kwargs));
2297 2357
2298 if (Py_EnterRecursiveCall(" while calling a Python object")) { 2358 if (Py_EnterRecursiveCall(" while calling a Python object")) {
2299 return NULL; 2359 return NULL;
2300 } 2360 }
2301 2361
2302 if (PyFunction_Check(callable)) { 2362 if (PyFunction_Check(callable)) {
2303 result = _PyFunction_FastCallDict(callable, args, nargs, kwargs); 2363 result = _PyFunction_FastCallDict(callable, args, nargs, kwargs);
2304 } 2364 }
2305 else if (PyCFunction_Check(callable)) { 2365 else if (PyCFunction_Check(callable)) {
2306 result = _PyCFunction_FastCallDict(callable, args, nargs, kwargs); 2366 result = _PyCFunction_FastCallDict(callable, args, nargs, kwargs);
2307 } 2367 }
2308 /* 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)
2309 else if (Py_TYPE(callable)->tp_fastcall) { 2369 && Py_TYPE(callable)->tp_fastcall) {
2310 fastternaryfunc fastcall = Py_TYPE(callable)->tp_fastcall; 2370 fastternaryfunc fastcall = Py_TYPE(callable)->tp_fastcall;
2311 2371
2312 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);
2313 } 2374 }
2314 else { 2375 else {
2315 PyObject *tuple; 2376 PyObject *tuple;
2316 2377
2317 /* Slow-path: build a temporary tuple */ 2378 /* Slow-path: build a temporary tuple */
2318 call = Py_TYPE(callable)->tp_call; 2379 call = Py_TYPE(callable)->tp_call;
2319 if (call == NULL) { 2380 if (call == NULL) {
2320 PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", 2381 PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
2321 callable->ob_type->tp_name); 2382 callable->ob_type->tp_name);
2322 goto exit; 2383 goto exit;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
2401 if (stack == NULL) { 2462 if (stack == NULL) {
2402 PyErr_NoMemory(); 2463 PyErr_NoMemory();
2403 return NULL; 2464 return NULL;
2404 } 2465 }
2405 } 2466 }
2406 2467
2407 /* use borrowed references */ 2468 /* use borrowed references */
2408 stack[0] = obj; 2469 stack[0] = obj;
2409 memcpy(&stack[1], args, (alloc - 1) * sizeof(PyObject *)); 2470 memcpy(&stack[1], args, (alloc - 1) * sizeof(PyObject *));
2410 2471
2411 assert(!PyErr_Occurred());
2412 result = _PyObject_FastCallKeywords(func, 2472 result = _PyObject_FastCallKeywords(func,
2413 stack, nargs + 1, 2473 stack, nargs + 1,
2414 kwnames); 2474 kwnames);
2415 if (stack != small_stack) { 2475 if (stack != small_stack) {
2416 PyMem_Free(stack); 2476 PyMem_Free(stack);
2417 } 2477 }
2418 2478
2419 result = _Py_CheckFunctionResult(func, result, NULL);
2420 return result; 2479 return result;
2421 } 2480 }
2422 2481
2423 PyObject * 2482 PyObject *
2424 _PyStack_AsDict(PyObject **values, PyObject *kwnames) 2483 _PyStack_AsDict(PyObject **values, PyObject *kwnames)
2425 { 2484 {
2426 Py_ssize_t nkwargs = PyTuple_GET_SIZE(kwnames); 2485 Py_ssize_t nkwargs;
2427 PyObject *kwdict; 2486 PyObject *kwdict;
2428 Py_ssize_t i; 2487 Py_ssize_t i;
2429 2488
2489 assert(kwnames != NULL);
2490 nkwargs = PyTuple_GET_SIZE(kwnames);
2430 kwdict = _PyDict_NewPresized(nkwargs); 2491 kwdict = _PyDict_NewPresized(nkwargs);
2431 if (kwdict == NULL) { 2492 if (kwdict == NULL) {
2432 return NULL; 2493 return NULL;
2433 } 2494 }
2434 2495
2435 for (i = 0; i < nkwargs; i++) { 2496 for (i = 0; i < nkwargs; i++) {
2436 PyObject *key = PyTuple_GET_ITEM(kwnames, i); 2497 PyObject *key = PyTuple_GET_ITEM(kwnames, i);
2437 PyObject *value = *values++; 2498 PyObject *value = *values++;
2438 assert(PyUnicode_CheckExact(key)); 2499 /* If key already exists, replace it with the new value */
2439 assert(PyDict_GetItem(kwdict, key) == NULL);
2440 if (PyDict_SetItem(kwdict, key, value)) { 2500 if (PyDict_SetItem(kwdict, key, value)) {
2441 Py_DECREF(kwdict); 2501 Py_DECREF(kwdict);
2442 return NULL; 2502 return NULL;
2443 } 2503 }
2444 } 2504 }
2445 return kwdict; 2505 return kwdict;
2446 } 2506 }
2447 2507
2448 static int 2508 int
2449 _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs, 2509 _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
2450 PyObject ***p_stack, PyObject **p_kwnames) 2510 PyObject ***p_stack, PyObject **p_kwnames)
2451 { 2511 {
2452 PyObject **stack, **kwstack; 2512 PyObject **stack, **kwstack;
2453 Py_ssize_t nkwargs; 2513 Py_ssize_t nkwargs;
2454 Py_ssize_t pos, i; 2514 Py_ssize_t pos, i;
2455 PyObject *key, *value; 2515 PyObject *key, *value;
2456 PyObject *kwnames; 2516 PyObject *kwnames;
2457 2517
2458 assert(nargs >= 0); 2518 assert(nargs >= 0);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2500 kwstack[i] = value; 2560 kwstack[i] = value;
2501 i++; 2561 i++;
2502 } 2562 }
2503 2563
2504 *p_stack = stack; 2564 *p_stack = stack;
2505 *p_kwnames = kwnames; 2565 *p_kwnames = kwnames;
2506 return 0; 2566 return 0;
2507 } 2567 }
2508 2568
2509 PyObject * 2569 PyObject *
2510 _Py_FastCall_FromArgs(PyObject *self, fastternaryfunc fastcall, 2570 _Py_RawFastCallDict(PyObject *self, fastternaryfunc fastcall,
2511 PyObject **args, Py_ssize_t nargs, PyObject *kwargs) 2571 PyObject **args, Py_ssize_t nargs, PyObject *kwargs)
2512 { 2572 {
2513 PyObject **stack; 2573 PyObject **stack;
2514 PyObject *kwnames; 2574 PyObject *kwnames;
2515 PyObject *result; 2575 PyObject *result;
2516 2576
2517 assert(!PyErr_Occurred()); 2577 assert(!PyErr_Occurred());
2578 assert(fastcall != NULL);
2579 assert(kwargs == NULL || PyDict_Check(kwargs));
2518 2580
2519 if (_PyStack_UnpackDict(args, nargs, kwargs, &stack, &kwnames) < 0) { 2581 if (_PyStack_UnpackDict(args, nargs, kwargs, &stack, &kwnames) < 0) {
2520 return NULL; 2582 return NULL;
2521 } 2583 }
2522 2584
2523 result = fastcall(self, stack, nargs, kwnames); 2585 result = fastcall(self, stack, nargs, kwnames);
2524 if (stack != args) { 2586 if (stack != args) {
2525 PyMem_Free(stack); 2587 PyMem_Free(stack);
2526 } 2588 }
2527 Py_XDECREF(kwnames); 2589 Py_XDECREF(kwnames);
2528
2529 result = _Py_CheckFunctionResult(self, result, NULL);
2530 return result; 2590 return result;
2531 } 2591 }
2532 2592
2533 PyObject * 2593 PyObject *
2534 _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg s, 2594 _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg s,
2535 PyObject *kwnames) 2595 PyObject *kwnames)
2536 { 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
2537 assert(nargs >= 0); 2602 assert(nargs >= 0);
2538 assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); 2603 assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
2539 2604
2540 /* 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
2541 be unique: these checks are implemented in Python/ceval.c and 2606 be unique: these checks are implemented in Python/ceval.c and
2542 _PyArg_ParseStack(). */ 2607 _PyArg_ParseStackAndKeywords(). */
2543 2608
2544 if (PyFunction_Check(callable)) { 2609 if (PyFunction_Check(callable)) {
2545 /* 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
2546 return _PyFunction_FastCallKeywords(callable, stack, nargs, kwnames); 2611 return _PyFunction_FastCallKeywords(callable, stack, nargs, kwnames);
2547 } 2612 }
2548 if (PyCFunction_Check(callable)) { 2613 if (PyCFunction_Check(callable)) {
2549 return _PyCFunction_FastCallKeywords(callable, stack, nargs, kwnames); 2614 return _PyCFunction_FastCallKeywords(callable, stack, nargs, kwnames);
2550 } 2615 }
2551 else if (Py_TYPE(callable)->tp_fastcall) { 2616 else if (PyType_HasFeature(Py_TYPE(callable), Py_TPFLAGS_HAVE_FASTCALL)
2617 && Py_TYPE(callable)->tp_fastcall) {
2552 fastternaryfunc fastcall = Py_TYPE(callable)->tp_fastcall; 2618 fastternaryfunc fastcall = Py_TYPE(callable)->tp_fastcall;
2553 PyObject *result; 2619 PyObject *result;
2554 2620
2555 if (Py_EnterRecursiveCall(" while calling a Python object")) { 2621 if (Py_EnterRecursiveCall(" while calling a Python object")) {
2556 return NULL; 2622 return NULL;
2557 } 2623 }
2558 2624
2559 result = fastcall(callable, stack, nargs, kwnames); 2625 result = fastcall(callable, stack, nargs, kwnames);
2560 result = _Py_CheckFunctionResult(callable, result, NULL); 2626 result = _Py_CheckFunctionResult(callable, result, NULL);
2561 2627
(...skipping 752 matching lines...) Expand 10 before | Expand all | Expand 10 after
3314 /* Free's a NULL terminated char** array of C strings. */ 3380 /* Free's a NULL terminated char** array of C strings. */
3315 void 3381 void
3316 _Py_FreeCharPArray(char *const array[]) 3382 _Py_FreeCharPArray(char *const array[])
3317 { 3383 {
3318 Py_ssize_t i; 3384 Py_ssize_t i;
3319 for (i = 0; array[i] != NULL; ++i) { 3385 for (i = 0; array[i] != NULL; ++i) {
3320 PyMem_Free(array[i]); 3386 PyMem_Free(array[i]);
3321 } 3387 }
3322 PyMem_Free((void*)array); 3388 PyMem_Free((void*)array);
3323 } 3389 }
LEFTRIGHT

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